2013-12-09 41 views
2

我想做什么

我想创建一些线程,比如线程A,B,C,并阻塞它们直到发生事件。发生事件时,我只想释放一个线程。如何仅发出一个线程来唤醒每个事件

例如:

Before event occurs: 
Thread A : blocked 
Thread B : blocked 
Thread C : blocked 

After event occurs: 
Thread A : blocked 
Thread B : unblocked 
THread C : blocked 

我读到AutoResetEvent可以做到这一点,但我不能指定要解锁哪个线程,并ManualResetEvent将解除所有阻塞的线程。

有没有办法实现我想要做的事情?

+0

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 –

+0

你如何确定哪个线程应该被解除阻塞? – Lukazoid

+0

从就绪队列中弹出的线程将成为将被解除阻塞的线程。 – kabichan

回答

3

创建ManualResetEvent的多个实例,每个Thread一个,并在每个Thread例如Thread中使用ManualResetEvent.WaitOne()

public void StartThreadA() 
{ 
    _mreA = new ManualResetEvent(); 
    _threadA = new Thread(new ThreadStart(() => 
    { 
     _mreA.WaitOne(); 
     // Continue 
    }); 
} 

当你甚至会发生,你就可以处理它,像这样:

private void OnSomeEvent() 
{ 
    _mreA.Set(); 
} 

这是在规模非常有限的,如果你打算使用大量线程的,我会建议使用一个字典来查找每个线程的ManualResetEvent

更新

正如我现在知道你正在使用的线程队列,我会做类似如下:

private Queue<ManualResetEvent> _queuedThreads = new Queue<ManualResetEvent>(); 

public void EnqueueThread() 
{ 
    var mre = new ManualResetEvent(); 
    var thread = new Thread(new ThreadStart(() => 
    { 
     mre.WaitOne(); 
     // Continue 
    }); 

    _queuedThreads.Enqueue(mre); 
} 

private void OnEvent() 
{ 
    var mre = _queuedThreads.Dequeue(); 
    mre.Set(); 
} 
+0

谢谢!我会试试这个。 – kabichan

0

您应该考虑使用一个信号量,而不是一个ManualResetEvent的或的AutoResetEvent 。

在文档here中有一个很好的基本示例。这个是related stack overflow question

+0

谢谢你的建议。但是在这个特殊的问题中,我不得不挂起/恢复线程而不使用已弃用的方法,锁或者半焦。 – kabichan

+0

除非您通过'Thread'使用'Semaphore'或'SemaphoreSlim',否则仍然无法控制要恢复哪个'Thread'。 – Lukazoid