我有一个关于System.Threading Microsoft .NET命名空间的问题。在此命名空间中,定义了许多类以帮助我使用线程进行管理。
好吧,我有一个问题,但是我不知道该用什么,MSDN含糊不清,我仍然不知道什么类在做什么。特别是我的问题涉及同步。

问题

我有一定数量的线程(考虑N个线程)。
在某个时刻,一个线程必须停止并等待另一个线程中的至少一个做某事。
一旦N-1个线程中的一个完成某项任务,该线程就会发出通知,停止的线程将能够继续执行。

因此,这只是一个同步问题:一个线程必须等待发出信号,仅此而已。

很多类

System.Threading中,提供了许多类来处理同步问题。有WaitHandle,有AutoResetEvent,有ManualResetEvent等...

我应该使用哪一位?

问题

我的问题是:有人可以总结一下我应该使用哪个类(class)来解决我的问题?您能否说出这些类(class)或其他类(class)之间最重要的区别?

关键是我还没有真正了解同步中负责什么类:例如,WaitHandleAutoResetEventManualResetEvent之间有什么区别?

那锁呢?

为了处理许多线程问题,.net提供了lock功能和Monitor类。这对夫妇满足我的需求吗?

谢谢

最佳答案

Albahari's book很棒,您应该花点时间仔细阅读。它最近长大了!

你想要什么

您需要一个 EventWaitHandle (EWH),它们很不错,因为没有任何可传递的内容,它们用于发信号通知线程(在相同或不同的进程中),并且顾名思义,可以等待它们。

使用方式

您可以在正在等待的线程上打开一个,然后使用另一个线程要知道的给定名称打开它。然后,您在该等待句柄上等待。

信令线程将打开一个具有相同名称(名称是字符串)的现有等待句柄,并在其上调用 set

差异性

AutoResetEvent s ManualResetEvent s都是从EWH继承的,它们实际上只是EWH的,它们的行为有所不同。您只想选择哪一个取决于您是想让EWH充当登机口还是转向。仅在您多次使用等待句柄或在一个以上的线程上等待该等待句柄时,您才关心这一点。我已经使用了等待处理量(我想),而且我认为我从未使用过手册。

重要须知

  • 无论您做什么,都不要传递等待句柄的实例,它们是由自己的线程分别打开的。您指定的名称将确保它们是“相同”的等待句柄。
  • 如果线程处于不同的进程中,则必须在EWH的名称前添加@"Global\"前缀,否则,等待句柄的名称将封装在同一进程中。另外,如果您在同一过程中都使用它们,请不要使用全局 namespace 。如果您不指定带反斜杠的前缀,则会自动添加一个反斜杠以保持其私密性,但是您无需知道该前缀。
  • 请记住,EWH可以被允许,如果遇到问题,我建议您使用EventWaitHandleRights.FullControl,但是您可以浏览完整的EventWaitHandleRights enumeration here
  • 我想用Guid.NewGuid().ToString("N")(Guid.NewGuidGuid.ToString)来命名EWH。我通常在创建信令线程时执行此操作,因为您当时可以轻松地将信息传递给它。因此,在这种情况下,初始线程将创建字符串,并将其在创建时传递给信令线程。这样,两个线程都知道名称,而不必进行任何奇特的跨线程传递变量。
  • EWH实现 IDisposable ,因此将其包装在 using block

  • 比赛条件

    EWH很不错,因为如果出于某种原因,信令线程在等待线程创建之前就打开了信号并向等待句柄发出了信号,那么一切将仍然有效,并且在等待线程到达时立即向等待线程发出信号。

    因此,因此,正在等待它的线程将需要进行一些错误捕获,因为您将需要调用 OpenExisting 。如果调用 ctor 's之一并且EWH已打开,则将收到here, under Exceptions所述的UnauthorizedAccessExceptionWaitHandleCannotBeOpenedException抛出。您仍然可以打开该EWH并获得所需的功能,您可能只需要打开它而不是创建它。

    关于c# - .NET Framework中的同步原语: which one is the good one?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6371299/

    10-11 00:41