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)的调用者是传递给Thread的方法,因此它应该使该线程休眠,而不是主UI线程NOPE!即使将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方法组。
希望这对您有帮助,队友!