9

我不确定要采用哪种策略...我专注于完成我的操作,但我也希望将性能问题控制在最低限度...有一个名为Execute()的方法必须等待(同步运行)直到操作完成。此操作发生在另一个线程上。有两种方法可以实现同一件事......

通过使用 ManualResetEvent

void Execute()
{
    taskHandle = new ManualResetEvent(false);
    .
    .
    //delegate task to another thread
    .
    .
    taskHandle.WaitOne();
}

或者

通过使用简单的 while 构造

void Execute()
{
    .
    .
    //delegate task to another thread
    .
    .
    while (!JobCompleted)
        Thread.Sleep(1000);
}

我应该采用两种方法中的哪一种……为什么?

编辑:

Q2。如果我只是在构建时有一个空的怎么办?有什么不同...?

while(!JobCompleted);

编辑:(我之前收集的东西)

http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - 本文说手动重置相对较慢,因为它们退出托管代码并重新进入......

4

7 回答 7

15

出于好奇,为什么ManualResetEvent而不是AutoResetEvent?无论哪种方式,通过睡眠检查睡眠方法使用操作系统原语。

您也可以使用Monitor锁(通过Monitor.EnterandMonitor.Exit或通过lock块显式使用),但该方法应基于您实际在做什么;如果是“只有其中一个,我需要独占访问”的场景那么使用Monitor锁。如果它是“我需要等到另一个线程由于资源访问以外的原因完成”,然后使用AutoResetEventor ManualResetEvent

Thread.Join当(且仅当)时,使用的建议是好的

  1. 您有权访问其他Thread对象
  2. 您不想在另一个线程终止之前执行。

如果其中一个不正确(您无权访问,或者另一个线程不会终止,它只会发出“全部清除”的信号),那么它就Thread.Join不可行。

最糟糕的选择是

while(!JobCompleted);

因为这将占用处理器不必要的变量检查,而它们之间没有任何停顿。是的,它会阻塞你的线程直到操作完成,但你会最大化 CPU 使用率(或至少一个核心的价值)。

于 2009-11-04T19:25:24.947 回答
4

该事件可以更有效地使用处理器 - 您不必唤醒父线程进行轮询。当事件触发时,内核会唤醒你。

于 2009-11-04T19:10:19.243 回答
2

如果您有权访问原始 Thread 对象,或者可以获得该访问权限,则最好使用Thread.Join().

编辑:此外,如果这发生在 WinForms 或 WPF 等 GUI 中,您可能需要考虑使用BackgroundWorker

于 2009-11-04T19:09:42.803 回答
2

使用的主要缺点Thread.Sleep()是您正在决定线程将等待多长时间。您正在等待的操作可能需要或多或少时间,而且通常很难精确量化该时间。如果线程睡眠时间过长,则说明您没有充分利用系统资源。

为了达到最佳效果,您应该使用ManualResetEvent(or AutoResetEvent) 以便在相关操作完成后立即恢复您的线程。

于 2009-11-04T19:12:38.600 回答
1

ManualResetEvent 绝对是要走的路。

从您提供的代码片段来看,您似乎是在 Execute 方法中委派执行。如果是这种情况,并且您只委派一个任务,那么如果您必须等待响应,为什么还要委派给另一个线程呢?您也可以只同步执行该过程。

于 2009-11-04T19:33:30.257 回答
1

手动重置相对较慢,因为它们退出托管代码并重新进入..

它们可能比等待/脉冲组合慢,我认为你应该在这里使用它。但是,Manual/AutoResetEvents即使Thread.Sleep(x)您选择x = 1. 即使您将 Windows 计时器分辨率降低到 1 毫秒。

如果我只是在构建时有一个空的怎么办?有什么不同...?

然后一个核心将以 100% 的速度旋转,直到条件变为真,从而从其他线程中窃取时间,这些线程可能会使用它来做一些有用的事情,比如计算“愤怒的小鸟”的帧数 - 或者 CPU 可以简单地冷却一点,延迟全球变暖的可怕影响再持续几纳秒。

于 2013-08-23T08:10:49.553 回答
0

两种方法基本上都做同样的事情。然而,while 循环更加明确,因为您可以指定睡眠时间。虽然我会使用 XXXResetEvent 类,这些类打算在您工作的场景中使用。我假设线程类现在或稍后将使用更强大的线程代码来实现,以处理多核处理器上的线程关联。

于 2009-11-04T19:18:09.893 回答