如果你願意做一點重構,我建議從Monitor切換到EventWaitHandle
派生類之一。
取決於你想你可能想AutoResetEvent
的行爲,將更加緊密地像一個Monitor.Entier(obj)
/Monitor.Exit(obj)
private readonly object _lockobj = new Object();
public void LockResource()
{
Monitor.Enter(_lockobj);
}
public void FreeResource()
{
Monitor.Exit(_lockobj);
}
//Which is the same as
private readonly AutoResetEvent _lockobj = new AutoResetEvent(true);
public void LockResource()
{
_lockobj.WaitOne();
}
public void FreeResource()
{
_lockobj.Set();
}
,或者你想ManualResetEvent
會喜歡更緊密地行事Monitor.Wait(obj)
/Monitor.PulseAll(obj)
private readonly object _lockobj = new Object();
public void LockResource()
{
Monitor.Enter(_lockobj);
}
public bool WaitForResource()
{
//requires to be inside of a lock.
//returns true if it is the lock holder.
return Monitor.Wait(_lockobj);
}
public void SignalAll()
{
Monitor.PulseAll(_lockobj);
}
// Is very close to
private readonly ManualResetEvent _lockobj = new ManualResetEvent(true);
public bool LockResource()
{
//Returns true if it was able to perform the lock.
return _lockobj.Reset();
}
public void WaitForResource()
{
//Does not require to be in a lock.
//if the _lockobj is in the signaled state this call does not block.
_lockobj.WaitOne();
}
public void SignalAll()
{
_lockobj.Set();
}
1個事件可以喚醒多個線程,可以通過一個線程處理多個事件
ManualResetEvent resetEvent0 = ...
ManualResetEvent resetEvent1 = ...
public int WaitForEvent()
{
int i = WaitHandle.WaitAny(new WaitHandle[] {resetEvent0, resetEvent1});
return i;
}
和i
將是已調用Set()
的重置事件的索引。
你看過['WaitHandle.WaitAny'](https://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitany(v = vs.110).aspx)嗎?雖然,如果您正在使用'Monitor'而不是像'ManualResetEvent'那樣的東西,那麼您可能無法使用它。 –
看到與一個線程等待兩個對象相關的代碼會很有幫助。 –
@ScottChamberlain目前使用'Monitor.PulseAll'來喚醒所有消費者線程。我關於'ManualResetEvent'的問題是,一個事件可以用於多個消費者線程還是應該是1個事件1線程?如果1個事件可以用於所有線程,你如何處理來自多線程的重置? @devlincarnate它實際上並不等待兩個對象,它等待一個對象,然後檢查是否需要爲任何數據集執行任何操作。 – phill