C# 为什么WPF';在主线程上运行时,调用不会导致死锁吗?

C# 为什么WPF';在主线程上运行时,调用不会导致死锁吗?,c#,.net,wpf,multithreading,dispatcher,C#,.net,Wpf,Multithreading,Dispatcher,以代码为例: public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void button_Click(object sender, RoutedEventArgs e) { //System.Threading.Thr

以代码为例:

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");
        }
    }
当然,
按钮\u单击
会在主线程上运行

我的理解是,
button.Dispatcher.Thread
是主线程,
Invoke()。但是,在这种情况下主线程不是被阻塞了吗?也就是说,主线程正在等待
Dispatcher.Invoke()
调用完成,而
Dispatcher.Invoke()
正在等待主线程释放。所以我预计这里会出现僵局,但不会出现僵局

为什么?


附言:我知道在这种情况下,我不需要调度程序
调用
,我可以直接调用
按钮。Content=“1234”
。我试图理解为什么在这种情况下僵局不会发生。

我相信您的误解可能是基于以下思考过程:

嗯,Invoke会阻止调用线程,直到操作完成。如果线程被阻止,它如何在线程上执行操作

如果我们查看源代码内部,就会发现回调不仅在同一个线程上被调用,而且直接*在Invoke方法内部被调用。主线程没有被阻塞

如果查看dispatcher的页面,可以在
Invoke
方法实现中的
If
语句上方看到以下注释,其中调用了回调:

// 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)
的整个主体只是对上述代码所在的方法的调用。

您不需要该调度器;正如你所说,你在ui线程上;只需使用按钮即可。Content=“1234”@是的,我知道。我试图理解,为什么当我调用dispatcher.Invoke(…)时,死锁不会发生,所以实际上,你问的是一个问题,而不是一个解决方案。。。?WPF是如此的好…情况似乎很正常:你的按钮点击run并将一个代理推入你的应用程序的处理管道这个问题毫无意义。死锁只能在至少涉及两个线程时发生。这里你只有一个——UI线程。@Clemens,看Nick的答案。如果不存在IF条件,则会发生死锁。编辑:刚刚看到其他的评论。如果是这种情况,为什么建议在调用调用之前自己调用CheckAccess()?您是否有提供建议的源代码?这是我第一次听说。即使没有立即调用dispatcher操作(而是排队等待稍后执行),也不会出现死锁,因为除了UI线程之外没有其他线程。@Clemens我相信Frank对他的误解的心态与“嗯,
Invoke
阻塞调用线程,直到操作完成。如果线程被阻塞,它如何在线程上执行操作?”我将此添加到我的回答中以澄清。