我正在使用一个使用ManualResetEvent同步线程的应用程序。FxCop让我处理那些对象。我发现下面的讨论告诉我同样的道理:
我需要释放()还是关闭() 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()之后,-call将多次释放它,并且可能会在其他线程仍在等待时释放它。
创建事件的线程没有对它的任何引用。setter-线程不应该释放它,因为还有其他线程在等待这个MRE。每个等待线程都不能像前面提到的那样释放它。
所以问题是:什么时候应该处理这个ManualResetEvent?
发布于 2013-08-29 15:53:57
当您不再需要ManualResetEvent时,应该对它进行处理。你真正的问题是,“我怎么知道我不再需要它了?”
通常,在执行线程时会通知某些内容,并且在线程上调用加入。或者线程设置了一些事件来指示它已经完成。如果您有多个线程,它们都可以向CountdownEvent发送信号。还有其他几种管理线程通知的方法。
关键是,如果你在分配资源,那就取决于你是否正确地处理了这些资源。在上面的代码中,您无法跟踪哪些线程正在执行,哪些线程与哪个ManualResetEvent相关联。如果您想确保正确地处理了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
}是的,这是很多工作。如果您可以构造您的程序,使您不必做这种事情,这可能是最好的。
https://stackoverflow.com/questions/18513805
复制相似问题