2009-12-31 2 views
8

Являются ли переменные состояния & мониторами, используемыми в C#?Переменные условий в C#

Может ли кто-нибудь дать мне пример?

+2

Как блокирующее заявление и класс Monitor, взгляните на WaitHandles (http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx), который может быть очень полезным и избавить вас от скучного шаблона. – Skurmedel

ответ

12

Эквивалент условной переменной, которая используется только для передачи сигналов в .NET является абстрактным классом WaitHandle. Практическими реализациями являются классы ManualResetEvent и AutoResetEvent.

Для переменной условия, которую вы используете в качестве монитора, требуется System.Threading.Monitor. Оператор C# lock делает его очень простым в использовании, он гарантирует, что монитор всегда выходит без явного программирования вызова Exit().

+2

Обратите внимание, что выход из монитора, если код генерирует исключение, не обязательно хорош; монитор, вероятно, защищал мутацию, чтобы гарантировать, что результат после выхода из монитора был последовательным; исключение свидетельствует о том, что мутация была только частично завершена, и поэтому вы только что разблокировали доступ к несогласованному состоянию. Если исключение поймано и программа продолжается, вы не можете полагаться на согласованное состояние программы. –

+0

Очень хороший момент, я переформулировал это. Благодарю. –

+5

Подождите (простите за каламбур). Действительно ли какой-либо из них является прямым эквивалентом переменной условия? Для моего не-экспертного глаза они не похожи на переменную условия. Фактически я видел веб-страницу, где показано, как построить переменную условия из объектов ядра Windows, таких как события автоматического перезапуска, и это довольно сложный процесс, включающий более одного такого объекта ядра ... – mackenir

3

Вы можете использовать объект Lock, который действует как синтаксический сахар для класса Monitor.

lock(someObject) 
{ 
    // Thread safe code here. 
} 

http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.80%29.aspx

+3

Одна небольшая коррекция, это не объект, а ключевое слово, и написано в нижнем регистре, 'lock' :) – Skurmedel

+0

Спасибо, развивался в VB.NET на работе, так что SyncLock на мозге и просто удалил часть Sync heh , –

2

В качестве альтернативы ManualResetEvent и друзьям Windows теперь предоставляет native support для переменных условия. Я не тестировал его сам, но есть хорошие шансы, что ваша производительность улучшится при использовании собственного API.

Вот статья код проекта, который объясняет, как получить доступ к этому (относительно новый) строится из C#:

A .NET Wrapper for the Vista/Server 2008 Condition Variable

0

Эта версия атомарно разблокирует мьютекс или ReaderWriterLockSlim во время ожидания для сигнализации, и повторно устанавливается защита его перед возвращением - это путь posix.

using System.Collections.Concurrent; 

namespace System.Threading.More { 
    public class ConditionVariable { 
     private readonly ConcurrentQueue<ManualResetEventSlim> _waitingThreads = new ConcurrentQueue<ManualResetEventSlim>(); 

     /// <summary> 
     ///  Atomically unlocks and waits for a signal. 
     ///  Then relocks the mutex before returning 
     /// </summary> 
     /// <param name="mutex"></param> 
     public void Wait(Mutex mutex) { 
      if (mutex == null) { 
       throw new ArgumentNullException("mutex"); 
      } 
      var waitHandle = new ManualResetEventSlim(); 
      try { 
       _waitingThreads.Enqueue(waitHandle); 
       mutex.ReleaseMutex(); 
       waitHandle.Wait(); 
      } finally { 
       waitHandle.Dispose(); 
      } 
      mutex.WaitOne(); 
     } 

     public void WaitRead(ReaderWriterLockSlim readerWriterLock) { 
      if (readerWriterLock == null) { 
       throw new ArgumentNullException("readerWriterLock"); 
      } 
      var waitHandle = new ManualResetEventSlim(); 
      try { 
       _waitingThreads.Enqueue(waitHandle); 
       readerWriterLock.ExitReadLock(); 
       waitHandle.Wait(); 
      } finally { 
       waitHandle.Dispose(); 
      } 
      readerWriterLock.EnterReadLock(); 
     } 

     public void Signal() { 
      ManualResetEventSlim waitHandle; 
      if (_waitingThreads.TryDequeue(out waitHandle)) { 
       waitHandle.Set(); 
      } 
     } 

     public void Broadcast() { 
      ManualResetEventSlim waitHandle; 
      while (_waitingThreads.TryDequeue(out waitHandle)) { 
       waitHandle.Set(); 
      } 
     } 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^