【问题标题】:Allow a child thread to call a delegate to the parent when the parent is in a join state waiting on the child in c#当父级处于连接状态时,允许子线程调用父级的委托,在c#中等待子级
【发布时间】:2013-02-18 23:00:36
【问题描述】:

我有一个表单负责创建和设置一个对象的实例,然后告诉该对象去做它的工作。这个过程很长,所以表单上有一个区域显示状态消息,让用户知道正在发生的事情。使用 setMessage(string msg) 函数设置消息。为了让表单保持对事件的响应,我为要运行的对象创建了一个新线程,并将 setMessage 函数作为委托传递给它,以允许对象在表单上设置状态消息。这部分工作正常。主窗体是响应式的,发布到其 setMessage 函数的消息按预期显示。

因为这个过程很长,并且由许多步骤组成,所以我想让用户在它完成之前终止它。为此,我创建了一个名为 _stopRequested 的 volatile bool 和一个名为 shouldStop() 的函数,该函数返回其值。这也作为委托给对象。对象可以通过定期检查 shouldStop() 来判断它是否应该终止,如果为真,则正常关闭。

最后,Windows 控件不是线程安全的,因此如果创建控件的线程以外的线程试图操作它,编译器会报错。因此,setMessage 函数被包装在一个 if 语句中,该语句对此进行测试,如果它是从工作线程调用的,则使用父线程调用该函数(有关说明,请参见 http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx)。

当用户请求关闭时,就会出现问题。主窗体将 _stopRequested 设置为 true,然后在关闭应用程序之前等待子线程完成。它通过执行 _child.Join() 来做到这一点。现在父线程(运行表单的线程)处于 Join 状态,不能做任何事情。子线程(运行长进程)检测到停止标志并尝试关闭,但在此之前,它通过调用它的 setMessage 委托来发布状态消息。该委托指向主窗体,它表明设置消息的线程(子)与创建控件(父)并在父线程中调用函数的线程不同。当然,父线程处于 Join 状态,并且在子线程终止之前不会在文本框上设置文本。子线程不会终止,因为它正在等待它调用的委托返回。瞬间死锁。

我找到了发出线程终止信号的示例,我还找到了子线程向父线程发送消息的示例,但是我找不到任何同时发生这两种事情的示例。有人可以给我一些关于如何避免这种僵局的指示吗?具体来说,我希望表单在关闭应用程序之前等到子线程终止,但在它等待时仍然可以工作。

提前感谢您的建议。

【问题讨论】:

  • GUI 事件处理程序中的 Join() - 经典的 Join 生成的死锁。第一种尝试方法 - 如果您只是注释掉 Join() 会发生什么?
  • 第二种方法 - 发布另一个“ThreadActionCompleted”委托作为线程的最后一行,(当然,转储加入)。
  • ..然后试着忘记你曾经听说过 Join() :)
  • ..不要再等待 GUI 事件处理程序中的任何内容 :)

标签: multithreading delegates deadlock


【解决方案1】:

1-(lazy) 从新线程中调度方法,使其不会锁定

2-(重新思考)主 UI 线程应该可以控制子线程,所以忘记 _stopRequested 和 shouldStop() 并实现 childThread.Abort() ,abort 不会杀死线程,而是发送一个ThreadAbortException 可以处理甚至取消

catch(ThreadAbortException e)
{
    ReleaseResources();
}

通过进行各种检查来确保 ReleaseResources 的安全,例如:

resource != null

resource.IsClosed()

ReleaseResources 应该在没有中止的情况下正常调用,也可以通过中止调用。

3-(如果可能)通过主线程调用 ReleaseResources() 停止子进程

您可能需要同时实现这些。

【讨论】:

    猜你喜欢
    • 2018-02-20
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 2019-02-03
    • 2017-09-20
    • 2011-04-28
    • 1970-01-01
    相关资源
    最近更新 更多