2009-12-31 52 views
8

Biến điều kiện là & màn hình được sử dụng trong C#?Biến điều kiện trong C#

Ai đó có thể cho tôi ví dụ không?

+2

Cũng như khóa-lệnh và lớp Monitor, hãy xem WaitHandles (http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx) có thể rất hữu ích và giúp bạn tiết kiệm từ bản mẫu nhàm chán. – Skurmedel

Trả lời

12

Tương đương với một biến điều kiện mà bạn sử dụng chỉ dành riêng cho tín hiệu trong .NET là lớp WaitHandle trừu tượng. Triển khai thực tế của nó là các lớp ManualResetEvent và AutoResetEvent.

Biến điều kiện mà bạn sử dụng làm màn hình yêu cầu System.Threading.Monitor. Câu lệnh C# lock làm cho nó rất dễ sử dụng, nó đảm bảo màn hình luôn luôn thoát mà không cần lập trình lệnh Exit() một cách rõ ràng.

+2

Lưu ý rằng thoát khỏi một màn hình nếu mã ném một ngoại lệ không nhất thiết phải là một điều tốt; màn hình có thể bảo vệ một đột biến để đảm bảo rằng kết quả khi thoát khỏi màn hình là nhất quán; một ngoại lệ là bằng chứng cho thấy đột biến chỉ được hoàn thành một phần và do đó bạn vừa mở khóa quyền truy cập vào trạng thái không nhất quán. Nếu ngoại lệ bị bắt và chương trình tiếp tục thì bạn không thể dựa vào trạng thái chương trình là nhất quán. –

+0

Điểm rất hay, tôi đã nói lại điều đó. Cảm ơn. –

+5

Đợi (tha thứ chơi chữ). Có bất kỳ cái nào thực sự tương đương trực tiếp với biến điều kiện không ?? Với mắt không chuyên gia của tôi, chúng không giống như biến điều kiện. Trong thực tế, tôi đã thấy một trang web cho thấy cách xây dựng biến điều kiện từ các đối tượng hạt nhân windows như các sự kiện tự động đặt lại, và đó là một quá trình khá phức tạp liên quan đến nhiều hơn một đối tượng hạt nhân như vậy ... – mackenir

3

Bạn có thể sử dụng đối tượng Khóa hoạt động như đường cú pháp cho lớp Monitor.

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

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

+3

Một sửa chữa nhỏ, nó không phải là một đối tượng, nhưng một từ khóa, và là viết thường chữ, 'khóa' :) – Skurmedel

+0

Cảm ơn, đã được phát triển trong VB.NET tại nơi làm việc, do đó, đã SyncLock trên não và chỉ cần loại bỏ phần Sync heh . –

2

Để thay thế cho ManualResetEvent và bạn bè, Windows hiện cung cấp native support cho các biến điều kiện. Tôi đã không chuẩn bị nó bản thân mình, nhưng có một cơ hội tốt hiệu suất của bạn sẽ cải thiện khi tận dụng các API bản địa.

Dưới đây là một bài viết Mã dự án giải thích làm thế nào để truy cập vào đây (tương đối mới) xây dựng từ C#:

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

0

Phiên bản này nguyên tử mở ra một Mutex hay ReaderWriterLockSlim trong khi chờ tín hiệu, và khóa lại nó trước khi trở về - đó là cách 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(); 
      } 
     } 
    } 
} 
Các vấn đề liên quan