gpt4 book ai didi

c# - 何时应处置 ManualResetEvent?

转载 作者:太空狗 更新时间:2023-10-29 23:15:32 24 4
gpt4 key购买 nike

我正在使用一个使用 ManualResetEvent 同步线程的应用程序。 FxCop 告诉我处理这些对象。我发现以下讨论告诉我相同的内容:

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-thread 不应该处理它,因为还有其他线程在等待这个 MRE。每个等待线程都无法像前面提到的那样处理它。

那么问题来了:这个ManualResetEvent应该在什么时候被释放?

最佳答案

ManualResetEvent 应该在您不再需要时被释放。您真正的问题是,“我怎么知道我不再需要它了?”

通常当线程完成时会收到通知,然后您调用 Join在线程上。或者线程设置一些事件来指示它已经完成。如果你有多个线程,它们都可以发出 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
}

是的,这是很多工作。如果您可以构建您的程序,这样您就不必做这种事情,那可能是最好的。

关于c# - 何时应处置 ManualResetEvent?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18513805/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com