当线程使用调度程序并且主线程正在等待线程完成时发生死锁 [英] Deadlock when thread uses dispatcher and the main thread is waiting for thread to finish

查看:86
本文介绍了当线程使用调度程序并且主线程正在等待线程完成时发生死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以解释一下为什么会造成死锁,以及如何解决死锁吗?

Can someone please explain why this creates a deadlock, and how to solve it?

        txtLog.AppendText("We are starting the thread" + Environment.NewLine);

        var th = new Thread(() =>
        {

            Application.Current.Dispatcher.Invoke(new Action(() => // causes deadlock
            {
                txtLog.AppendText("We are inside the thread" + Environment.NewLine); // never gets printed
                // compute some result...
            }));


        });

        th.Start();
        th.Join(); // causes deadlock
        // ... retrieve the result computed by the thread

说明:我需要我的辅助线程来计算结果,并将其返回给主线程.但是辅助线程还必须将调试信息写入日志.并且日志位于wpf窗口中,因此线程需要能够使用dispatcher.invoke().但是当我执行Dispatcher.Invoke时,就会发生死锁,因为主线程正在等待辅助线程完成,因为它需要结果.

Explanation: I need my secondary thread to compute a result, and to return it to the main thread. But the secondary thread must also write debug informations to the log; and the log is in a wpf window, so the thread needs to be able to use the dispatcher.invoke(). But the moment I do Dispatcher.Invoke, a deadlock occurs, because the main thread is waiting for the secondary thread to finish, because it needs the result.

我需要一个模式来解决这个问题.请帮助我重写此代码. (请编写实际代码,不要只说使用BeginInvoke").谢谢.

I need a pattern to solve this. Please help me rewrite this code. (Please write actual code, do not just say "use BeginInvoke"). Thank you.

而且,从理论上讲,我不了解一件事:只有当两个线程以不同的顺序访问两个共享资源时,才会发生死锁.但是在这种情况下实际的资源是什么?一种是GUI.但是另一个是什么?我看不到.

Also, theoretically, I don't understand one thing: a deadlock can only happen when two threads access two shared resources in different orders. But what are the actual resources in this case? One is the GUI. But what is the other? I can't see it.

通常通过强加线程只能按精确顺序锁定资源的规则来解决死锁.我已经在其他地方做到了.但是,由于我不了解实际的资源是什么,该如何在这种情况下强加此规则?

And the deadlock is usually solved by imposing the rule that the threads can only lock the resources in a precise order. I've done this already elsewhere. But how can I impose this rule in this case, since I don't understand what the actual resources are?

推荐答案

简短的答案:使用BeginInvoke()代替Invoke(). 长答案会改变您的方法:请参见替代方法.

Short answer: use BeginInvoke() instead of Invoke(). Long answer change your approach: see the altenative.

当前,您的Thread.Join()导致主线程被阻塞,以等待辅助线程的终止,但是辅助线程正在等待主线程执行您的AppendText操作,因此您的应用程序死锁了.

Currently your Thread.Join() is causing that main thread get blocked waiting for the termination of secondary thread, but secondary thread is waiting to main thread executes your AppendText action, thus your app is deadlocked.

如果您更改为BeginInvoke(),那么您的第二个线程将不会等到主线程执行您的操作.取而代之的是,它将使您的调用排队并继续.您的主线程不会在Join()上被阻止,因为您的第二线程这次成功结束了.然后,当主线程完成时,此方法将可以自由处理对AppendText的排队调用

If you change to BeginInvoke() then your seconday thread will not wait until main thread executes your action. Instead of this, it will queue your invocation and continues. Your main thread will not blocked on Join() because your seconday thread this time ends succesfully. Then, when main thread completes this method will be free to process the queued invocation to AppendText

替代:

void DoSomehtingCool()
{
    var factory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
    factory.StartNew(() =>
    {
        var result = await IntensiveComputing();
        txtLog.AppendText("Result of the computing: " + result);
    });
}

async Task<double> IntensiveComputing()
{
    Thread.Sleep(5000);
    return 20;
}

这篇关于当线程使用调度程序并且主线程正在等待线程完成时发生死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆