【发布时间】:2014-08-11 01:15:40
【问题描述】:
更新现在不是问题。没有意识到 Dispatcher.Invoke 方法内外返回的 theadID 不同。
据我了解,当使用 async 时,正在等待的任务 T1 将在不同的线程中执行,并且等待后面的代码被包装为任务 T2,其 ContinueWith 为 T1。所以我假设 threadcontextID 在下面的代码中会有所不同。但是下面的代码生成相同的 ThreadContextID。是不是我的理解错了?
另外,为什么我必须在 T1 中使用 Dispatcher,而在 T2 中可以直接更新主 UI? threadContext 开关在 async/await 中如何工作?谢谢。
更新: T1 中的代码正在 VS 调试线程视图的 MainThread 中执行。但是,如果是在主线程中,为什么我不能直接更新 UI?它给了我 CrossThread 异常。
async private void AsyncTask(object sender, RoutedEventArgs e)
{
OutputDialog.Text = Thread.CurrentThread.ManagedThreadId+ Environment.NewLine + OutputDialog.Text;
Task T1 = new Task(
() => {
Thread.Sleep(5000);
OutputDialog.Dispatcher.Invoke(() => {
OutputDialog.Text = "Task in AWAIT" + Environment.NewLine + OutputDialog.Text;
OutputDialog.Text = Thread.CurrentThread.ManagedThreadId + Environment.NewLine + OutputDialog.Text;
});
});
T1.Start();
await T1;
//T2
OutputDialog.Dispatcher.Invoke(() => { OutputDialog.Text = "Continued Task after AWAIT 1" + Environment.NewLine + OutputDialog.Text; });
OutputDialog.Text = "Continued Task after AWAIT 2" + Environment.NewLine + OutputDialog.Text;
OutputDialog.Text = Thread.CurrentThread.ManagedThreadId + Environment.NewLine + OutputDialog.Text;
}
UI 的 xaml 代码
<Grid>
<StackPanel>
<Button Click="AsyncTask">Execute now</Button>
<TextBox Name="OutputDialog" Background="Gray" Foreground="Yellow" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch">
</TextBox>
</StackPanel>
</Grid>
【问题讨论】:
-
您的意思是
Thread.CurrentThread.ManagedThreadId而不是Thread.CurrentContext?线程和上下文之间没有 1:1 的关系(System.Runtime.Remoting.Contexts.Context,这就是Thread.CurrentContext返回的内容)。两个不同的线程可以在同一个上下文中执行。更多细节:stackoverflow.com/a/22761023/1768303. -
@Noseratio 是的,你是对的。我已经更新了代码。但是,使用 T1.ConfigurateAwait(true) 或 T1.ConfigurateAwait(false),它仍然输出相同的 ManagedThreadID。
-
你是说你的代码的最后一行显示了相同的线程ID?对于您访问
ManagedThreadID的其他两行,它应该是相同的,因为您通过Dispatcher.Invoke执行它,因此代码在 UI 线程上运行。 -
@Noseratio 你又是对的。 Dispatcher.Invoke 回到主线程。所以它捕获了 MainThread ID。对 Inovke 的调用在工作线程上。
-
async捕获当前同步上下文并使用它来执行await表示的延续任务。在 WPF 应用程序中,上下文是 UI 线程,因此T2在那里运行。默认情况下,T1将在线程池线程上运行,因此您需要使用调度程序手动将操作编组到 UI 线程。
标签: c# asynchronous async-await threadcontext