![](/img/trans.png)
[英]What resources do AutoResetEvent / ManualResetEvent consume?
[英]What does AutoResetEvent.Set() do ?
如果我這樣做:
private static System.Threading.AutoResetEvent event_2 = new System.Threading.AutoResetEvent(false);
然后在主線程中我做:
event_2.Set();
它將狀態從false
更改為true
?
如果是這樣,它基本上做到了:
AutoResetEventState = !AutoResetEventState
?
它將狀態設置為允許線程在Wait()
上繼續執行的狀態。
如果有任何線程已經在等待,那么將允許一個線程進行並且狀態將立即設置為未設置,因此所有其他線程將繼續阻塞。
如果當前沒有線程正在等待,那么將立即允許第一個等待,但后續線程將阻塞。
其他EventWaitHandle
派生的類共享相同的通用機制,但允許進行的線程的自動重置與ManualResetEvent
不同,因此名稱也不同。
如果將true
傳遞給構造函數,則初始狀態發出信號(允許線程進行),如果傳遞false
則不發出信號,因此傳遞true
與構造后立即調用Set()
相同,而傳遞false
則相反就像你調用Reset()
。
線程通過在AutoResetEvent上調用WaitOne來等待信號。 如果AutoResetEvent處於非信號狀態,則線程阻塞,等待當前控制資源的線程通過調用Set來指示資源可用。
調用Set信號AutoResetEvent釋放等待線程。 AutoResetEvent保持信號狀態,直到釋放單個等待線程,然后自動返回到非信號狀態。 如果沒有線程在等待,則狀態將無限期地發出信號。
要添加到其他答案,您需要這個的原因(而不是具有bool
屬性,您只需切換)是:
信令:將在e.WaitOne()
處阻止的線程將發出信號 ,其中一個將繼續。 如果你想在沒有同步原語的情況下自己這樣做,你必須實現某種輪詢; “阻塞”線程必須定期輪詢bool
(或者說, int
)字段以檢查它是否已更改並允許繼續。 如果不出意外,這會不必要地消耗cpu周期並且會有延遲(取決於你的輪詢間隔)。
原子性:如果多個線程在等待,您可以保證只有一個線程將被解除阻塞。 使用所提到的輪詢解決方案確保相同的行為將需要使用鎖定或原子指令(如在Interlocked
類中找到的那些)以及對可能的編譯器和處理器指令重新排序/存儲器障礙的良好理解。
如果您正在尋找一種簡單的方法來同步多個線程,這是.NET中最簡單的(如果不是最簡單的)解決方案之一。 創建生產者/消費者隊列非常簡單:
// Simplified example. Check http://www.albahari.com/threading/part2.aspx
// for detailed explanations of this and other syncronizing constructs
private readonly AutoResetEvent _signal = new AutoResetEvent(false);
private readonly ConcurrentQueue<Something> _queue = new ConcurrentQueue<Something>();
// this method can be called by one or more threads simultaneously
// (although the order of enqueued items cannot be known if many threads are competing)
void ProduceItem(Something s)
{
_queue.Enqueue(s); // enqueue item for processing
_signal.Set(); // signal the consumer thread if it's waiting
}
// this loop should be running on a separate thread.
void ConsumerLoop()
{
while (!_ending)
{
// block until producer signals us
_signal.WaitOne();
// process whatever is enqueued
Something s = null;
while (!_ending && _concurrentQueue.TryDequeue(out s))
{
Process(s);
}
}
}
您需要注意的一件事是,對Set
多次連續調用不一定會多次向WaitOne
發出信號。 在此示例中,多個生成器可能會觸發Set
方法,但是在上下文切換發生並且ConsumerLoop
繼續之前可能需要幾毫秒,這意味着只有一個Set
將被有效地處理。
另一個線程正在使用event_2.Wait()等待事件,並從線程調用.Set(),等待線程將繼續執行。
如果是這樣,它基本上做到了:
AutoResetEventState =!AutoResetEventState
?
除此之外,它還將EventWaitHandle
設置為允許一個或多個線程繼續進行的信令狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.