【问题标题】:Thread.Abort() creates deadlock when worker thread calls Dispatcher.Invoke()当工作线程调用 Dispatcher.Invoke() 时,Thread.Abort() 创建死锁
【发布时间】:2015-08-29 23:44:29
【问题描述】:

两个线程:main (GUI) 和 worker。工人要求主使用Dispatcher.Invoke(...) 进行更新。在某些时候,由于用户干预,我必须使用Thread1.Abort() 中止工作人员。但是这样的顺序似乎造成了死锁:

  1. T1 调用一个动作
  2. 主线程中止 T1

我知道,Aborting 是邪恶的(我应该怎么做?每两行插入 CheckIfCanceled() ??),但假设它是必要的 - 我怎样才能防止死锁?

【问题讨论】:

  • 使用 Dispatcher.Invoke() 而不是 Dispatcher.BeginInvoke() 的重点是可以使用它的返回值。并且您可以抛出异常并在线程中捕获它。这为您提供了两种出色的方法来停止线程而无需中止它。
  • 您真的需要立即中止线程吗?你不能在线程的主循环中检查一次(或几次)IsCancellationRequested 吗?
  • @HansPassant,我不明白你的意思。我怎样才能以这种方式停止线程?我有一个长时间运行的工作线程,它不时要求 GUI 调用,这对我有什么帮助?
  • 这似乎没有任何意义,提到 Dispatcher.Invoke() 似乎是多余的。请改用 Task 类。它支持使用 CancellationToken 取消,从而避免了对容易死锁的 Abort() 的需要。并让您在 UI 线程上运行代码,而无需使用 Dispatcher、TaskScheduler.FromCurrentSynchronizationContext。
  • 打电话给Thread.Abort 就像向司机的头部开枪来停车一样。汽车会停下来,但不知道它会在这个过程中造成什么损害。

标签: c# multithreading deadlock


【解决方案1】:

在 Windows 线程模型中,您不能从其执行上下文之外中止线程。您应该向工作线程发出信号以退出其工作方法(然后终止线程),为此您可以使用 CancellationToken 或其他跨线程标志之类的东西。 Thread.Abort() 会抛出异常,但是当您将它与锁定多线程算法一起使用时,并不能真正保证执行此操作的时间。

您最好的选择是使用BeginInvoke() 调用,然后使用WaitHandle 等待答案(这会暂停线程而无需花费CPU 周期等待循环)。当主线程处理您的调用请求时,它将通过WaitHandle 发出信号,表明该线程可以恢复。使用标志来指示线程是否必须在恢复时退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多