Как я могу сообщить потоку, чтобы он прекратил ждать мьютекса после его соединения? - PullRequest
2 голосов
/ 04 ноября 2010

Я заметил, что некоторые из моих служб зависали, а не выключались, как было указано в инструкции, потому что они ожидали блокировок, удерживаемых другими службами, которые ожидают их выключения (вызывая тупик).Для этого мне нужно было каким-то образом сигнализировать потокам, ожидающим завершения блокировки, поэтому я придумал следующее:

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.В конце концов, соединение вступит в силу, и поток будет прерван, но я бы предпочел, чтобы он не пришел к этому.

Поэтому у меня два вопроса:

  1. Есть ликаким-то образом поток узнает, что он присоединен (и, следовательно, может перестать ждать)?

  2. Есть ли лучший способ решить эту проблему, чем то, что я придумал здесь?

Ответы [ 2 ]

2 голосов
/ 04 ноября 2010

Создайте глобальное событие ручного сброса, установите его при отключении службы перед присоединением к своим потокам и используйте WaitHandle.WaitAny (mutex, stopEvent) в вашей функции Lock:

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
  }
}
1 голос
/ 04 ноября 2010

Вы должны встроить механизм отмены в задачу, в которой работают ваши потоки, поэтому никакой механизм потоков, кроме отмены, не может помочь.http://www.albahari.com/threading/part3.aspx#_Cancellation_Tokens

...