C# 线程上下文
这是一个传参的解决方法:在业务处理线程中设置参数,当前业务线程和之后创建的子线程可以获取参数,而不必修改方法(函数)原型。
0x00 问题
0x01 解决
/// <summary> /// 线程上下文。 /// </summary> /// <typeparam name="TContext">上下文类型。</typeparam> public sealed class ThreadContext<TContext> : MarshalByRefObject #if NETFRAMEWORK , System.Runtime.Remoting.Messaging.ILogicalThreadAffinative #endif where TContext : class { /// <summary> /// 当前线程上下文。 /// </summary> public static TContext Current #if NETFRAMEWORK { [System.Security.SecuritySafeCritical] set { var threadContext = System.Runtime.Remoting.Messaging.CallContext.GetData(currentId) as ThreadContext<TContext>; if (threadContext == null) { threadContext = new ThreadContext<TContext>(); System.Runtime.Remoting.Messaging.CallContext.SetData(currentId, threadContext); } threadContext.Context = value; } [System.Security.SecuritySafeCritical] get => (System.Runtime.Remoting.Messaging.CallContext.GetData(currentId) as ThreadContext<TContext>)?.Context; } [DebuggerBrowsable(DebuggerBrowsableState.Never)] static readonly string currentId = $"Orchid.Threading.ThreadContext({typeof(TContext).FullName})"; #else { set { if (_currentContext.Value == null) _currentContext.Value = new ThreadContext<TContext>(); _currentContext.Value.Context = value; } get => _currentContext.Value?.Context; } [DebuggerBrowsable(DebuggerBrowsableState.Never)] static readonly System.Threading.AsyncLocal<ThreadContext<TContext>> _currentContext = new System.Threading.AsyncLocal<ThreadContext<TContext>>(); #endif [DebuggerBrowsable(DebuggerBrowsableState.Never)] TContext Context { set; get; } ThreadContext() { } }
0x02 测试
using NUnit.Framework; using System.Threading.Tasks; public class ThreadContextTest { [Test] public void TestMethod() { var isRunning = false; object context = null, context1 = null, context2 = null; var task = Task.Run(() => { ThreadContext<object>.Current = context = 0; Task.Factory.StartNew(() => { context1 = ThreadContext<object>.Current; ThreadContext<object>.Current = 1; }).Wait(); while (!isRunning) System.Threading.Thread.Sleep(200); }); Task.Run(() => { ThreadContext<object>.Current = context2 = 2; isRunning = true; }).Wait(); task.Wait(); Assert.NotNull(context); Assert.NotNull(context1); Assert.NotNull(context2); Assert.AreEqual(context, context1); Assert.AreNotEqual(context, context2); } }
0x03 总结

浙公网安备 33010602011771号