一个简单的问题。这是 WinForms 应用程序的一部分:
void Form1_Load(object sender, EventArgs e)
{
var task2 = Task.Factory.StartNew(() => MessageBox.Show("Task!"),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
Debug.WriteLine("Before Exit");
MessageBox.Show("Exit!");
}
有人可以解释为什么我看到“任务!”首先,然后当我运行它时“退出”?
当我看到“任务!”消息框,“退出前”已在调试输出中打印。
编辑:更简单,相同的效果:
void Form1_Load(object sender, EventArgs e)
{
SynchronizationContext.Current.Post((_) =>
MessageBox.Show("Task!"), null);
Debug.WriteLine("Before Exit");
MessageBox.Show("Exit!");
}
编辑:如果我用
MessageBox.Show("Exit!")
替换 Form { Text = "Exit!" }.ShowDialog()
,我会按预期看到“退出”,然后是“任务”。这是为什么? 最佳答案
.NET 框架中 Win32 消息泵的确切细节没有记录。请注意,Win32 API 历来允许重入行为。
当您的代码启动任务时,它使用的任务调度程序将请求任务在当前 SynchronizationContext
上执行。所以它最终调用 SynchronizationContext.Current.Post
,非常类似于你的第二个代码示例。WindowsFormsSynchronizationContext
通过将 Win32 消息发布到消息队列来工作;消息类型是 .NET 内部定义的一种,表示“执行此代码”。 (这些细节没有记录)。
当您的代码继续调用 MessageBox.Show
时,它会运行一个嵌套的消息循环,这就是执行排队操作的原因。如果您删除了 Exit!
消息框,那么操作将在 Form1_Load
返回到 Application.Run
中的顶级消息循环后执行。
关于c# - Task.Factory.StartNew 和同步上下文,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21907829/