我正在创建一个库,该库依赖于捕获SynchronizationContext以便将回调发布回UI线程。

用户处于一种奇怪的状况,该回调被改为发布到ThreadPool。经过研究,我提出了以下两个测试用例:

1:

public partial class Form1 : Form
{
    private Test test;

    public Form1()
    {
        test = new Test();
        InitializeComponent();
    }

    private class Test
    {
        public Test()
        {
            if (SynchronizationContext.Current == null)
                throw new InvalidOperationException("It's null! :(");
        }
    }
}


2:

public partial class Form1 : Form
{
    private Test test = new Test();

    public Form1()
    {
        InitializeComponent();
    }

    private class Test
    {
        public Test()
        {
            if (SynchronizationContext.Current == null)
                throw new InvalidOperationException("It's null! :(");
        }
    }
}


第一个测试运行正常,但是第二个测试抛出异常。为什么?

最佳答案

在第二个示例中,new Test()(几乎)作为程序中的第一个代码运行。您的Main函数可能会调用new Form1(),而后者立即会调用new Test()

SynchronizationContext必须存在(显然)之前必须设置。在运行时中,没有任何魔术可以猜测您的应用程序将使用WinForms。使用WinForms是一个动态的运行时决定。当您使用WinForms时,WinForms将设置其SynchronizationContext(我忘记了确切的触发点)。

在第一个示例中,首先运行base构造函数(new Form()),这显然会安装SynchronizationContext

当您在任何WinForms代码运行之前运行代码时,将不会出现SynchronizationContext

您的库对此无能为力。您可以添加一个断言或手动设置WinForms同步上下文(为此提供了一个API),但这几乎不是库的事。图书馆不应与全球状态混为一谈。 (除非您的库明确是供WinForms专用的)。

关于c# - WinForms中SynchronizationContext为null,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28793383/

10-13 06:57