在 ManualResetEvent 或 Thread.Sleep() 之间进行选择

发布于 2024-08-10 16:11:32 字数 897 浏览 5 评论 0原文

我不确定要采用哪种策略...我专注于完成操作,但我也希望将性能问题控制在最小范围...有一种名为 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 结构怎么办?有什么区别...?

while(!JobCompleted);

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

http://www.yoda.arachsys.com /csharp/threads/waithandles.shtml - 这篇文章说手动重置相对较慢,因为它们退出托管代码并返回...

I am not sure which strategy to adopt...I am focusing on my operation getting completed, but I'd also like to keep performance issues to a min too...there is a method called Execute() which has to wait (run synchronously) until an operation completes. This operation happens on another thread. There are 2 ways to implement the same thing...

By using ManualResetEvent

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

OR

By using a simple while construct

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

Which one of the two approaches should I adopt...why?

EDIT:

Q2. What if I just had an empty while contruct? Whats the difference...?

while(!JobCompleted);

EDIT: (something I gathered before)

http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - This article says manualresets are comparitively slower because they go out of managed code and back in...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

朮生 2024-08-17 16:11:32

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

您还可以使用 Monitor 锁(通过 Monitor.EnterMonitor.Exit 显式使用,或者通过 lock > 块),但该方法应该基于您实际正在做的事情;如果是“只有这些事物之一并且我需要独占访问”的场景,则使用Monitor锁。如果是“出于资源访问以外的原因,我需要等待另一个线程完成”,则使用 AutoResetEventManualResetEvent

那么使用 Thread.Join 的建议是好的。

  1. 如果(且仅当)您有权访问其他 Thread 对象并且
  2. 您不想在其他对象之前执行, 线程终止。

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

最糟糕的选择是

while(!JobCompleted);

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

Out of curiosity, why ManualResetEvent and not AutoResetEvent? Either way, go with the OS primitive over a sleep-check-sleep approach.

You could also use a Monitor lock (either explicitly through Monitor.Enter and Monitor.Exit, or through a lock block), but the approach should be based upon what you're actually doing; if it's a scenario of "there's only one of these things and I need exclusive access", then use a Monitor lock. If it's "I need to wait until the other thread finishes for reasons other than resource access", then use an AutoResetEvent or ManualResetEvent.

The suggestions to use Thread.Join are good if (and only if)

  1. You have access to the other Thread object
  2. You don't want to execute until the other thread terminates.

If either isn't true (you don't have access, or the other thread won't terminate, it will just signal an "all clear") then Thread.Join isn't viable.

The worst option is

while(!JobCompleted);

As that will tie up the processor with needless checks of the variable without any pause in between them. Yes, it will block your thread until the operation completes, but you'll max out CPU usage (or at least a single core's worth).

慈悲佛祖 2024-08-17 16:11:32

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

The event makes more efficient use of the processors- you're not having to wake the parent thread up to poll. The kernel will wake you up when the event fires.

三生殊途 2024-08-17 16:11:32

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

编辑:此外,如果这是在 WinForms 或 WPF 等 GUI 中发生的,您可能需要考虑使用 后台工作人员

If you have access to the original Thread object, or can get that access, you're best off using Thread.Join().

Edit: Also, if this is taking place in a GUI like WinForms or WPF, you may want to consider using BackgroundWorker

只是偏爱你 2024-08-17 16:11:32

使用 Thread.Sleep() 的主要缺点是您要决定线程将等待多长时间。您正在等待的操作可能会花费更多更少的时间,并且一般来说,精确量化该时间是非常困难的。如果线程休眠时间太长,那么您就没有充分利用系统资源。

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

The main disadvantage to using Thread.Sleep() is that you are making the decision on how long the thread will wait. The operation you are waiting for may take more or less time, and in general, it is very difficult to precisely quantify that time. If the thread sleeps too long, then you are not making best use of system resources.

In order to be optimal, you should use ManualResetEvent (or AutoResetEvent) so that your thread is resumed as soon as the dependent operation finishes.

浪菊怪哟 2024-08-17 16:11:32

ManualResetEvent 绝对是最佳选择。

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

ManualResetEvent is definitely the way to go.

From the code snippet you supplied, it looks like you are delegating the execution within your Execute method. If this is the case, and you are only delegating a single task, why are you delegating to another thread at all if you have to wait for the response? You may as well just execute the process synchronously.

痴意少年 2024-08-17 16:11:32

手动重置相对较慢,因为它们会退出托管代码并返回..

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

如果我只有一个空的 while 结构怎么办?有什么区别...?

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

manualresets are comparitively slower because they go out of managed code and back in..

They are probably slower than say a Wait/Pulse combo, which you should use here in my opinion. But Manual/AutoResetEvents will be way faster than any Thread.Sleep(x) that you do, even if you choose x = 1. And even if you lower the Windows timer resolution to 1ms.

What if I just had an empty while contruct? Whats the difference...?

Then one core will spin at 100% until the condition turns true, stealing away time from other threads that might instead use it to do something useful, like calculating frames for "Angry Birds" - or the cpu could simply cool off a bit, delaying the dire effects of global warming for some further nanoseconds.

雄赳赳气昂昂 2024-08-17 16:11:32

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

Both approaches do the same thing basically. The while loop is little bit more explicit however, since you can specify the sleep time. Although I would use the XXXResetEvent classes which are meant to be used in the scenario your working in. I would assume the threading classes would be implemented now or later with more robust threading code to handle maybe thread affinity on multi core processors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文