SynchronizationContext 为我们提供了一种从不同线程更新 UI 的方法(通过 Send 方法同步或通过 Post 方法异步)。
看看下面的例子:
private void SynchronizationContext SyncContext = SynchronizationContext.Current;
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(Work1);
thread.Start(SyncContext);
}
private void Work1(object state)
{
SynchronizationContext syncContext = state as SynchronizationContext;
syncContext.Post(UpdateTextBox, syncContext);
}
private void UpdateTextBox(object state)
{
Thread.Sleep(1000);
string text = File.ReadAllText(@"c:\temp\log.txt");
myTextBox.Text = text;
}
SynchronizationContext.Current 将返回 UI 线程的同步上下文。我怎么知道这个?在每个表单或 WPF 应用程序开始时,上下文将在 UI 线程上设置。如果您创建一个 WPF 应用程序并运行我的示例,您会看到当您单击该按钮时,它会休眠大约 1 秒钟,然后它将显示文件的内容。您可能期望它不会,因为 UpdateTextBox 方法的调用者(即 Work1)是传递给线程的方法,因此它应该休眠该线程而不是主 UI 线程,不!即使 Work1 方法被传递给一个线程,请注意它也接受一个对象,即 SyncContext。如果您看一下,您会发现 UpdateTextBox 方法是通过 syncContext.Post 方法而不是 Work1 方法执行的。看看以下内容:
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread.Sleep(1000);
string text = File.ReadAllText(@"c:\temp\log.txt");
myTextBox.Text = text;
}
最后一个例子和这个例子执行相同。两者都不会在工作时阻止 UI。
总之,将 SynchronizationContext 视为一个线程。它不是线程,它定义了一个线程(请注意,并非所有线程都有 SyncContext)。每当我们在其上调用 Post 或 Send 方法来更新 UI 时,就像从主 UI 线程正常更新 UI 一样。如果由于某些原因,您需要从不同的线程更新 UI,请确保该线程具有主 UI 线程的 SyncContext,然后使用您要执行的方法调用其上的 Send 或 Post 方法,您就可以了放。
希望这对你有帮助,伙计!