一个简单的问题。这是 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/

10-13 08:08