我正在创建一个库,该库依赖于捕获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/