当前位置:  开发笔记 > 编程语言 > 正文

为什么逻辑调用上下文不跨线程传播?

如何解决《为什么逻辑调用上下文不跨线程传播?》经验,为你挑选了1个好方法。

我有一个奇怪的问题,逻辑调用上下文没有传播到我的应用程序中的线程.

在此示例中,线程(在设置逻辑调用上下文数据之前创建)不会获取新值:

class Program
{
    static void Main(string[] args)
    {
        var dispatcher = new MessageDispatcher();

        //Logical call context data not set yet
        Console.WriteLine($"Main: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}"); // Main logical call context data is not set yet = Null
        dispatcher.Broadcast("a string"); // logical call context data is still not set yet = Null

        //Logical call context data is set now
        CallContext.LogicalSetData("myvar", "Logical call context variable");
        Console.WriteLine($"Main: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}"); // Main logical call context data is set = return value

        dispatcher.Broadcast("a string"); // Logical call context data is set and should return the data set above?

        Console.ReadLine();
    }
    public class MessageDispatcher
    {
        private readonly ConcurrentQueue _messages;
        private readonly AutoResetEvent _waitHandle;
        private bool _terminate;
        private bool _messageMonitoringActive;

        public MessageDispatcher()
        {
            _messages = new ConcurrentQueue();
            _waitHandle = new AutoResetEvent(false);

            var thread = new Thread(MonitorCollection);
            thread.Start();
        }

        public void Broadcast(string message)
        {
            _messages.Enqueue(message);
            _waitHandle.Set();
        }

        private void MonitorCollection()
        {
                _waitHandle.WaitOne();

                string message;
                while (_messages.TryDequeue(out message))
                {
                    Console.WriteLine(
                        $"{message}: {Thread.CurrentThread.ManagedThreadId}: {CallContext.LogicalGetData("myvar")}");
                }
        }
    }
}

对于在创建的线程内进行的所有调用,不会从刚刚设置的上下文变量中采用调用上下文数据.这是为什么?

在我的应用程序中,我无法在实例化时设置逻辑调用上下文变量(这是在启动时通过IoC完成的(它是一个WebAPI堆栈)),但仅限于每次调用.



1> khellang..:

在MSDN文档指出,

CallContext是一个专门的集合对象,类似于方法调用的线程本地存储,并提供对每个逻辑执行线程唯一的数据槽.插槽不在其他逻辑线程上的调用上下文之间共享.可以将对象添加到CallContext中,因为它向下移动并备份执行代码路径,并通过路径上的各种对象进行检查.

还有那个

CallContext中的所有方法都是静态的,并且在当前Thread中的调用上下文中操作.

只是阅读文档,你会认为这种情况不起作用.而这对于真正SetDataGetData方法; 如果你SetData在一个线程上使用,你必须GetData在同一个线程上使用才能恢复数据.

但是有一个例外; SetLogicalData而且GetLogicalData,你已经在使用它了.这些设计用于通过"逻辑线程"流动上下文,即跨越相同的线程通过子线程.

您的方法的问题是您在创建和启动子线程尝试传递数据,这将无法正常工作.如果你搬家

CallContext.LogicalSetData("myvar", "Logical call context variable");

以上

var dispatcher = new MessageDispatcher();

即在创建和启动线程之前(在MessageDispatcher构造函数中).你会看到你正确地获得了价值.

换一种说法; 您需要确保在创建和启动子线程之前设置所有数据.

推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有