【问题标题】:Co-ordinating worker thread shutdown协调工作线程关闭
【发布时间】:2011-11-01 15:41:52
【问题描述】:

我有一个List(Of IWorker),其中包含许多混凝土。 IWorker 又具有Startup()Shutdown() 方法。

在 Worker 类中,Startup() 创建一个新的工作线程然后返回。 Shutdown() 目前设置了一个私有 ShutDownRequested 标志并返回。工作线程检查标志(最坏的情况是每隔几秒)。

这一切正常,但目前父应用无法确定 Worker 是否已完成关闭。

我可以看到多种解决方法,但不确定哪种方法最好。

  • State 属性添加到IWorker。应该可以,但我要去投票州,这似乎有点讨厌。
  • 使关机命令阻塞 - 可能是我理想的解决方案,但我不确定如何实现它 - 工作人员 Sunclock 是否是一个私有对象,Shutdown() 也应该在设置标志后尝试同步?
  • 还有别的吗?

任何文章、建议或建议表示赞赏。 C# 或 VB 中的示例很好。

【问题讨论】:

  • 这取决于你想做什么以及为什么。拨打Shutdown()时要屏蔽吗?您想向用户显示状态吗?还有什么?
  • @svick 这是在控制台应用程序中运行的。目前,在调用启动工作人员后,控制台每隔几秒循环一次,从工作人员那里读取一些状态信息并显示它(处理的事件、使用的带宽等)。当用户按 Enter 键退出应用程序时,会向每个工作人员发送关闭信息。我只想等到关机完成,打印一个干净关机的确认,然后退出。如果应用程序没有关闭并且工作人员退出,它会被回收并重新启动。

标签: c# vb.net multithreading


【解决方案1】:

如果您希望关闭成为阻塞操作,我不会尝试使用锁定来阻塞 Shutdown()

如果您可以使用 .NET 4,我会将您的内部执行方法设置为任务。然后,您可以调用Task.Wait() 阻止,直到它完成。

如果您必须使用 .NET 3.5 或更早版本,我会在内部调用 Shutdown(),等待 WaitHandle,例如 ManualResetEvent。关闭代码可能如下所示:

' Include:
Private shutdownEvent as ManualResetEvent = new ManualResetEvent(false)

Sub Shutdown()
    ShutDownRequested = True
    shutdownEvent.WaitOne()
End Sub

然后轮询循环(线程操作)会这样做:

Sub Execute()
    While Not ShutDownRequested
        ' Do your work
    End While

    ' Before you exit, "set" the event:
    shutdownEvent.Set()
End Sub

【讨论】:

  • 使用任务,您还可以使用Task.WaitAll()轻松地一次等待所有任务。
  • 感谢您的详细回答。我目前在这个项目中停留在 3.5 中。您能否解释一下您的ManualResetEvent 比另一个答案中建议的使用Thread.Join 有什么好处?
  • @Basiclife 主要优点是:1)您可以(可选)在 WaitOne() 上设置一个超时,这将允许您返回并且不会在这种情况下永远阻塞写得不好的IWorker, 2) 你不必保留对线程的引用,这允许它在完成时被 GC'ed。 3) 发生的事情非常明确。
  • @Reed 感谢您的解释 - 一切都很好,我将来会使用它。
【解决方案2】:

有一个方法Thread.Join 会阻塞直到线程结束——有什么用吗?

【讨论】:

    【解决方案3】:

    为什么不在IWorker 上添加一个ShutdownComplete 事件,并确保它是每个混凝土完成后的最后一件事?我知道这听起来可能会迫使实现做一些特定的事情,但如果你有一个 IWorker 的基类,那应该是一件大事。考虑一下。

    public abstract class WorkerBase : IWorker
    {
      public event EventHandler ShutdownComplete;
      //...other implemenation details
    
      public void Shutdown()
      {
        this.ShutdownInternal();
        this.ShutdownComplete(this, EventArgs.Empty);
      }
    
      protected abstract void ShutdownInternal();
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 2011-01-13
      相关资源
      最近更新 更多