考虑代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
//System.Threading.Thread.CurrentThread = button.Dispatcher.Thread
button.Dispatcher.Invoke(() => button.Content = "1234");
}
}
当然,button_Click
在主线程上运行。
我的理解是button.Dispatcher.Thread
是主线程,只有当线程没有被阻塞时才会处理Invoke()
。但是,在这种情况下,主线程是否被阻止?即主线程正在等待Dispatcher.Invoke()
调用完成,Dispatcher.Invoke()
正在等待主线程释放。所以我希望在这里遇到僵局,但它不会陷入僵局。
为什么?
P.S:我知道在这种情况下我不需要Dispatcher.Invoke
,我可以直接拨打button.Content = "1234"
。我试图理解为什么在这种情况下不会发生死锁。
答案 0 :(得分:8)
我相信你的误解可能基于以下思维过程:
“好吧,Invoke会阻塞调用线程,直到操作完成。如果线程被阻塞,它如何在线程上执行操作?”
如果我们查看源代码,我们会看到回调不仅在同一个线程上调用,而且直接在Invoke方法内调用。主线程没有被阻塞。
如果查看调度程序的Reference Source页面,您可以在if
方法实现中的Invoke
语句上方看到以下注释,并在其中调用回调:
// Fast-Path: if on the same thread, and invoking at Send priority,
// and the cancellation token is not already canceled, then just
// call the callback directly.
if(!cancellationToken.IsCancellationRequested && priority == DispatcherPriority.Send && CheckAccess())
{
/* snipped */
callback();
/* snipped */
}
你在主线程上调用Dispatcher.Invoke
,该方法只需立即调用它即可处理。
*嗯,不是直接,但Invoke(Action)
的整个主体只是对上述代码所在方法的调用。