考虑以下代码:
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()
正在等待主线程释放。因此,我预计这里会出现僵局,但不会陷入僵局。
为什么?
PS:我知道在这种情况下我不需要Dispatcher.Invoke
,我可以button.Content = "1234"
直接致电。我试图理解为什么在这种情况下不会发生死锁。
我相信您的误解可能是基于以下思考过程:
“好吧,Invoke会阻塞调用线程,直到操作完成为止。如果线程被阻塞,它将如何对该线程执行操作?”
如果我们在源代码内部查看,我们不仅会在同一线程上调用回调,而且还会在Invoke方法内部直接*调用该回调。主线程未被阻止。
如果查看调度程序的“参考源”页面,则可以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)
过程只是对上面代码所在的方法的调用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句