Files
riojoy/src/RioJoy.Core/Compat/TaskCompat.cs
T
CydandClaude Fable 5 1ff0b16015 Phase 8A (2/2): RioJoy.Core multi-targets net48 + net40 (Windows XP flavor)
- TargetFrameworks net48;net40. net48 keeps x64 + ViGEm + System.IO.Ports
  package; net40 adds Microsoft.Bcl.Async + System.ValueTuple and uses the
  in-box SerialPort.
- Compat/TaskCompat bridges Task.Run/Delay/WhenAny/WhenAll (TaskEx on
  net40) and SemaphoreSlim.WaitAsync (net40 blocks briefly - trivial at
  9600 baud).
- IReadOnlyList/IReadOnlyDictionary -> IList/IDictionary throughout
  (net40 predates the IReadOnly* interfaces and the Bcl backport cannot
  make arrays implement them).
- HashCode.Combine replaced with a manual combine (Bcl.HashCode has no
  net40 build); Marshal.SizeOf<T> -> typeof form; ViGEmJoystickSink
  gated #if !NET40. HidFeederJoystickSink stays on both flavors - it
  will drive RioGamepadXP.sys on XP via the same contract.

Both TFMs build; 275 tests green on net48.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 20:41:58 -05:00

41 lines
1.6 KiB
C#

namespace RioJoy.Core.Compat;
/// <summary>
/// net48/net40 bridge for the handful of Task-era statics the code uses. On
/// net40 (the Windows XP flavor) these come from Microsoft.Bcl.Async's
/// <c>TaskEx</c>, and <c>SemaphoreSlim.WaitAsync</c> doesn't exist at all —
/// there the wait blocks briefly instead, which at 9600 baud (tiny writes,
/// rare contention) costs nothing measurable.
/// </summary>
internal static class TaskCompat
{
#if NET40
public static Task Run(Action action) => TaskEx.Run(action);
public static Task Delay(TimeSpan delay, CancellationToken cancellationToken) =>
TaskEx.Delay(delay, cancellationToken);
public static Task<Task> WhenAny(IEnumerable<Task> tasks) => TaskEx.WhenAny(tasks);
public static Task WhenAll(IEnumerable<Task> tasks) => TaskEx.WhenAll(tasks);
public static Task WaitAsync(SemaphoreSlim semaphore, CancellationToken cancellationToken)
{
semaphore.Wait(cancellationToken); // net40: no WaitAsync; block (see class doc)
return TaskEx.FromResult(true);
}
#else
public static Task Run(Action action) => Task.Run(action);
public static Task Delay(TimeSpan delay, CancellationToken cancellationToken) =>
Task.Delay(delay, cancellationToken);
public static Task<Task> WhenAny(IEnumerable<Task> tasks) => Task.WhenAny(tasks);
public static Task WhenAll(IEnumerable<Task> tasks) => Task.WhenAll(tasks);
public static Task WaitAsync(SemaphoreSlim semaphore, CancellationToken cancellationToken) =>
semaphore.WaitAsync(cancellationToken);
#endif
}