From 59bc2bfee0f496d434ce014cb76f704a44f18213 Mon Sep 17 00:00:00 2001 From: maxisoft Date: Tue, 3 Dec 2024 15:49:02 +0100 Subject: [PATCH] Use a workaround class To replace AsyncLocal --- ASFFreeGames/ASFFreeGamesPlugin.cs | 2 +- ASFFreeGames/Utils/Workarounds/AsyncLocal.cs | 75 ++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 ASFFreeGames/Utils/Workarounds/AsyncLocal.cs diff --git a/ASFFreeGames/ASFFreeGamesPlugin.cs b/ASFFreeGames/ASFFreeGamesPlugin.cs index a34723a..483b7da 100644 --- a/ASFFreeGames/ASFFreeGamesPlugin.cs +++ b/ASFFreeGames/ASFFreeGamesPlugin.cs @@ -40,7 +40,7 @@ internal static PluginContext Context { } // ReSharper disable once InconsistentNaming - private static readonly ThreadLocal _context = new(); + private static readonly Utils.Workarounds.AsyncLocal _context = new(); private static CancellationToken CancellationToken => Context.CancellationToken; public string Name => StaticName; diff --git a/ASFFreeGames/Utils/Workarounds/AsyncLocal.cs b/ASFFreeGames/Utils/Workarounds/AsyncLocal.cs new file mode 100644 index 0000000..a9cd673 --- /dev/null +++ b/ASFFreeGames/Utils/Workarounds/AsyncLocal.cs @@ -0,0 +1,75 @@ +using System; + +namespace Maxisoft.ASF.Utils.Workarounds; + +public sealed class AsyncLocal { + // ReSharper disable once StaticMemberInGenericType + private static readonly Type? AsyncLocalType; + +#pragma warning disable CA1810 + static AsyncLocal() { +#pragma warning restore CA1810 + try { + AsyncLocalType = Type.GetType("System.Threading.AsyncLocal`1") + ?.MakeGenericType(typeof(T)); + } + catch (InvalidOperationException) { + // ignore + } + + try { + AsyncLocalType ??= Type.GetType("System.Threading.AsyncLocal") + ?.MakeGenericType(typeof(T)); + } + + catch (InvalidOperationException) { + // ignore + } + } + + private readonly dynamic? Delegate; + private T? NonSafeValue; + + /// Instantiates an instance that does not receive change notifications. + public AsyncLocal() { + if (AsyncLocalType is not null) { + try { + Delegate = Activator.CreateInstance(AsyncLocalType)!; + } + catch (SystemException) { + // ignored + } + } + } + + /// Gets or sets the value of the ambient data. + /// The value of the ambient data. If no value has been set, the returned value is default(T). + public T? Value { + get { + if (Delegate is not null) { + try { + return Delegate.Value; + } + catch (SystemException) { + // ignored + } + } + + return (T) NonSafeValue!; + } + set { + if (Delegate is not null) { + try { + Delegate.Value = value!; + + return; + } + catch (SystemException) { + // ignored + } + } + + NonSafeValue = value; + } + } +}