【问题标题】:How can I signal a thread to stop waiting for a Mutex once it's been joined?加入后,如何向线程发出信号以停止等待 Mutex?
【发布时间】:2010-11-04 18:32:27
【问题描述】:

我注意到我的一些服务挂起而不是按照指示关闭,因为它们正在等待其他正在等待它们关闭的服务持有的锁(导致死锁)。为此,我需要一些方法来向等待锁关闭的线程发出信号,所以我想出了这个:

public static Boolean Lock(this Mutex mutex)
{
 Boolean achieved = false;

 while (Thread.CurrentThread.ThreadState != System.Threading.ThreadState.StopRequested)
 {
  try
  {
   achieved = mutex.WaitOne(TimeSpan.FromSeconds(10.0));
  }
  catch (AbandonedMutexException exception)
  {
   // Log this
  }
 }

 return achieved;
}

当每个服务停止时,它会在其每个线程上调用 Join。问题是即使在调用 Thread 之后,ThreadState 仍然设置为 Running。最终,Join 将超时并且线程将被中止,但我宁愿它不会发生这种情况。

所以我有两个问题:

  1. 有什么方法可以让线程知道它已被加入(因此可以停止等待)?

  2. 有没有比我在这里想出的更好的方法来解决这个问题?

【问题讨论】:

    标签: .net multithreading join wait


    【解决方案1】:

    创建一个全局手动重置事件,在加入线程之前将其设置为服务关闭,并在 Lock 函数中使用 WaitHandle.WaitAny (mutex, stopEvent):

    internal static EventWaitHandle s_stopEvent ;
    
    // in service startup code:
    s_stopEvent = new ManualResetEvent (false) ;
    
    public static void Stop (this IEnumerable<Thread> threads)
    {
      s_stopEvent.Set () ;
      foreach (var thread in threads)
        thread.Join () ;
    }
    
    public static bool Lock (this Mutex mutex)
    {
      try
      {
        return WaitHandle.WaitAny (new WaitHandle[] { mutex, s_stopEvent }) == 0 ;
      }
      catch (AbandonedMutexException exception)
      {
        // Log this
      }
    }
    

    【讨论】:

    • 您能详细说明一下吗?
    【解决方案2】:

    您必须在线程正在运行的任务中构建取消机制,因此除了取消之外,没有任何线程机制可以提供帮助。

    看看这里:

    http://www.albahari.com/threading/part3.aspx#_Cancellation_Tokens

    【讨论】:

    • 这个想法是取消令牌取代了我的加入,当我希望我的线程关闭时我抛出它并捕获取消异常?这似乎有点像中止,因为它无视状态。这是好习惯吗?有没有办法更优雅地做到这一点?
    • 是的,这是替代您的加入的另一种方法。工作线程正在做的将包括检查取消标志,在这种情况下它们将停止并且不需要加入。
    猜你喜欢
    • 2021-04-27
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多