如何最好地处理由于 AutoResetEvent.WaitOne() 而处于休眠状态的线程
本文关键字:休眠状态 线程 WaitOne 何最好 处理 理由 AutoResetEvent | 更新日期: 2023-09-27 17:57:18
我有一个Windows服务,它在5个线程之一中发送电子邮件(这样做是为了提高服务发送电子邮件的速度):
private AutoResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (this.messageQueue.TryDequeue(out message))
{
this.block.Set();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
我有一个Queue
方法,它将一条或多条新消息添加到 messageQueue 并调用block.Set()
以便 5 个线程中的一个可以发送消息。 当允许其中一个线程运行时,只要队列中有消息,就会调用block.Set()
,以便下一条消息可以取消排队,并且 5 个线程中的另一个线程将发送它。 依此类推,直到队列为空。 这一切都工作正常。
但是,当我释放我的对象时,我设置了处置变量,然后为每个线程设置:
if(thread.ThreadState == ThreadState.Running)
{
thread.Join();
}
else if(thread.ThreadState == ThreadState.WaitSleepJoin)
{
thread.Abort();
}
大多数情况下,线程由于block.WaitOne
而处于休眠状态,因此上面的代码中止了线程。 但是,这会导致记录线程中止异常。 我可以将线程中止异常与其他异常分开捕获并选择不记录,但它似乎不是很干净。
在不导致此过度日志记录的情况下清理这些线程的最佳方法是什么?
更新:
我已将上述内容更改为:
private ManualResetEvent block;
private ThreadedQueue<Message> messageQueue;
private void DoSend()
{
try
{
while(!this.disposing)
{
this.block.WaitOne();
Message message = null;
if (!this.messageQueue.TryDequeue(out message) && !this.disposing)
{
// There's nothing else to send for now to block the sending threads
// unless we're disposing as we want the other threads to exit too
this.block.Reset();
}
if(message != null)
{
this.Send(message);
}
}
}
catch(Exception ex)
{
// Log
}
}
public void Dispose()
{
this.disposing = true;
this.block.Set();
foreach(Thread thread in this.sendingThreads) {
thread.Join();
}
this.block.Dispose();
this.sendingThreads = null;
}
感谢您的帮助。
你正在玩一个非常危险的游戏。 您的代码特别容易出现死锁。 您将看到线程状态为 ThreadState.Running,线程在一微秒后调用 WaitOne()。 您的 Join() 调用将死锁并且永远不会返回。
您可以通过释放自动重置事件来获取在 WaitOne() 调用中被阻止的线程以取消阻止。 这将抛出一个可预测的异常,ObjectDisposedException,你可以捕获一个异常。 使用另一个 ManualResetEvent 来指示线程退出。 不需要这样使用 Thread.Abort()。
请改用 BlockingCollection。 它将生成简单干净和简短的代码,可以理解,管理和调试...
一个生产者五个消费者...线程 101.
http://msdn.microsoft.com/en-us/library/dd267312.aspx