C#报”DuplicateWaitObjectException”的原因以及解决办法

  • Post category:C#

.Net中的”DuplicateWaitObjectException”异常表示已存在的等待句柄对象无法被重复添加到同一个等待列表中。这通常是由于同步对象重复使用或重复等待的情况引起的。下面提供两个示例来详细说明原因和解决办法:

  1. 示例一

在该示例中,假设我们有两个线程,都在等待某种事件发生后触发。线程一创建了一个ManualResetEvent对象来等待事件发生,然后线程二也创建了一个ManualResetEvent对象,但在等待事件之前并未调用Set()方法设置事件。当线程二等待该事件时,.Net运行时抛出了”DuplicateWaitObjectException”异常,因为两个线程都在等待同一个对象。

解决此问题的方法是,线程二应该使用与线程一相同的ManualResetEvent对象,而不是创建一个新的对象。这样,当线程一等待时,线程二调用Set()方法就可以解除等待状态。

// 线程一
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
manualResetEvent.WaitOne();

// 线程二
ManualResetEvent manualResetEvent2 = manualResetEvent;
manualResetEvent2.WaitOne();
  1. 示例二

在该示例中,假设我们有两个线程,都在等待同一个Mutex。线程一在等待Mutex后,获取了Mutex,并未释放。然后,线程二也等待Mutex,并获得了同一个Mutex,此时.Net抛出了”DuplicateWaitObjectException”异常。

解决此问题的方法是,在释放Mutex之前,必须确保先退出线程一。否则,线程二将无法获取Mutex,从而无法继续执行。

// 线程一
Mutex mutex = new Mutex();
mutex.WaitOne();
// do something...

// 线程二
Mutex mutex2 = new Mutex();
mutex2.WaitOne();
// do something...

在这个例子中,如果线程一在调用mutex.ReleaseMutex()之前退出了,则线程二可以成功地获取到Mutex并继续执行自己的逻辑。

这两个示例说明了DuplicateWaitObjectException的原因和解决办法。确保在等待同步对象时,使用相同的对象并确保在释放对象之前先退出等待线程,这是避免此异常的关键。