Skip to content

Commit a9e0df8

Browse files
committed
Use a workaround class To replace AsyncLocal
1 parent c42f356 commit a9e0df8

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

ASFFreeGames/ASFFreeGamesPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ internal static PluginContext Context {
4040
}
4141

4242
// ReSharper disable once InconsistentNaming
43-
private static readonly ThreadLocal<PluginContext> _context = new();
43+
private static readonly Utils.Workarounds.AsyncLocal<PluginContext> _context = new();
4444
private static CancellationToken CancellationToken => Context.CancellationToken;
4545

4646
public string Name => StaticName;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
3+
namespace Maxisoft.ASF.Utils.Workarounds;
4+
5+
public sealed class AsyncLocal<T> {
6+
// ReSharper disable once StaticMemberInGenericType
7+
private static readonly Type? AsyncLocalType;
8+
9+
#pragma warning disable CA1810
10+
static AsyncLocal() {
11+
#pragma warning restore CA1810
12+
try {
13+
AsyncLocalType = Type.GetType("System.Threading.AsyncLocal`1")
14+
?.MakeGenericType(typeof(T));
15+
}
16+
catch (InvalidOperationException) {
17+
// ignore
18+
}
19+
20+
try {
21+
AsyncLocalType ??= Type.GetType("System.Threading.AsyncLocal")
22+
?.MakeGenericType(typeof(T));
23+
}
24+
25+
catch (InvalidOperationException) {
26+
// ignore
27+
}
28+
}
29+
30+
private readonly dynamic? Delegate;
31+
private T? NonSafeValue;
32+
33+
/// <summary>Instantiates an <see cref="AsyncLocal{T}"/> instance that does not receive change notifications.</summary>
34+
public AsyncLocal() {
35+
if (AsyncLocalType is not null) {
36+
try {
37+
Delegate = Activator.CreateInstance(AsyncLocalType)!;
38+
}
39+
catch (Exception) {
40+
// ignored
41+
}
42+
}
43+
}
44+
45+
/// <summary>Gets or sets the value of the ambient data.</summary>
46+
/// <value>The value of the ambient data. If no value has been set, the returned value is default(T).</value>
47+
public T? Value {
48+
get {
49+
if (Delegate is not null) {
50+
try {
51+
return Delegate.Value;
52+
}
53+
catch (Exception) {
54+
// ignored
55+
}
56+
}
57+
58+
return (T) NonSafeValue!;
59+
}
60+
set {
61+
if (Delegate is not null) {
62+
try {
63+
Delegate.Value = value!;
64+
65+
return;
66+
}
67+
catch (Exception) {
68+
// ignored
69+
}
70+
}
71+
72+
NonSafeValue = value;
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)