我正在使用一个使用 ManualResetEvent 同步线程的应用程序。 FxCop 让我处理掉这些物品。我发现以下讨论告诉我同样的事情:
我需要 Dispose() 或 Close() EventWaitHandle 吗? https://stackoverflow.com/questions/659840/do-i-need-to-dispose-or-close-an-eventwaithandle
但我不知道何时处置 ManualResetEvent 的实例。
以下简化代码演示了该问题:
private void btn_Click(object sender, EventArgs e)
{
var mre = new ManualResetEvent(false);
new Thread(() => this.SetEvent(mre)).Start();
for (int i = 0; i < 10; ++i)
{
new Thread(() => this.WaitFor(mre)).Start();
}
}
private void SetEvent(ManualResetEvent manualResetEvent)
{
Thread.Sleep(10000);
manualResetEvent.Set();
}
private void WaitFor(ManualResetEvent manualResetEvent)
{
manualResetEvent.WaitOne();
}
问题在于 ManualResetEvent 存在多个实例,并且多个线程正在等待每个实例。
如果我记住列表中的实例,我不知道何时处理它。在 WaitOne() 调用之后处置它会多次处置它,并且可能会在其他线程仍在等待时处置它。
创建该事件的线程没有任何对该事件的引用。 setter 线程不应该处置它,因为还有其他线程正在等待该 MRE。每个等待线程都无法像前面提到的那样处理它。
那么问题来了:这个ManualResetEvent应该什么时候处理掉呢?
The ManualResetEvent
当您不再需要它时应将其丢弃。您真正的问题是:“我怎么知道我不再需要它?”
通常,当线程完成时会收到通知,然后您调用Join http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx在线程上。或者线程设置一些事件来指示它已经完成。如果你有多个线程,它们都可以发出信号倒计时活动 http://msdn.microsoft.com/en-us/library/system.threading.countdownevent.aspx。还有几种其他方法可以管理线程通知。
关键是,如果您要分配资源,就需要您确保它们得到正确的处置。在上面的代码中,您没有任何方法可以跟踪哪些线程正在执行或哪些线程与哪些线程关联ManualResetEvent
。如果你想确保 MRE 被正确处置,那么你必须跟踪它,不仅跟踪 MRE,还跟踪哪些线程正在使用它,哪些线程已完成其工作,并在所有 MRE 被释放时收到通知。线程完成后,你就可以处理东西了。
在您的特定情况下,如果您确实必须以这种方式使用 MRE,我可能会创建一个包含对线程和 MRE 的引用的数据结构,以及一个CountdownEvent
线程完成时发出信号。就像是:
class WorkUnit
{
public List<Thread> Threads;
public ManualResetEvent MRE;
public CountdownEvent CE;
}
现在,当一个线程完成时,它会执行以下操作:
workUnit.CE.Signal();
程序的其他部分(可能是主线程)定期检查工作单元列表。对于该列表中的每个项目,它执行以下操作:
if (workUnit.CE.WaitOne(0))
{
foreach (Thread t in workUnit.Threads)
{
t.Join();
}
// dispose the MRE and the CE
// and remove the work unit from the list
}
是的,工作量很大。如果您可以构建您的程序,这样您就不必做这种事情,这可能是最好的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)