简体   繁体   English

在ManualResetEvent或Thread.Sleep()之间做出选择

[英]To make a choice between ManualResetEvent or Thread.Sleep()

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. 我不确定采用哪种策略...我专注于我的操作完成,但我也想将性能问题保持在最小...有一个名为Execute()的方法必须等待(同步运行)直到操作完成。 This operation happens on another thread. 此操作发生在另一个线程上。 There are 2 ways to implement the same thing... 有两种方法可以实现同样的事情......

By using ManualResetEvent 通过使用ManualResetEvent

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

OR 要么

By using a simple while construct 通过使用简单的while构造

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

Which one of the two approaches should I adopt...why? 我应采用两种方法中的哪一种......为什么?

EDIT: 编辑:

Q2. 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... http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - 这篇文章说手动复制比较慢,因为它们离开了托管代码并重新进入......

Out of curiosity, why ManualResetEvent and not AutoResetEvent ? 出于好奇,为什么ManualResetEvent而不是AutoResetEvent Either way, go with the OS primitive over a sleep-check-sleep approach. 无论哪种方式,通过睡眠 - 检查 - 睡眠方法与OS原语一起使用。

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; 您也可以使用Monitor锁(通过Monitor.EnterMonitor.Exit显式,或通过lock块),但方法应该基于您实际执行的操作; if it's a scenario of "there's only one of these things and I need exclusive access", then use a Monitor lock. 如果它是“只有这些东西之一 ,我需要独占访问”的场景,那么使用Monitor锁。 If it's "I need to wait until the other thread finishes for reasons other than resource access", then use an AutoResetEvent or ManualResetEvent . 如果它是“我需要等到另一个线程因资源访问以外的原因而完成 ”,那么使用AutoResetEventManualResetEvent

The suggestions to use Thread.Join are good if (and only if) 使用Thread.Join的建议很好(如果)

  1. You have access to the other Thread object 您可以访问其他Thread对象
  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. 如果其中任何一个不是真的(你没有访问权限,或者其他线程不会终止,它只会发出“全部清除”信号),那么Thread.Join就不可行了。

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). 是的,它将阻止你的线程,直到操作完成,但你将最大化CPU使用率(或至少一个核心的价值)。

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. 当事件触发时,内核会唤醒你。

If you have access to the original Thread object, or can get that access, you're best off using Thread.Join() . 如果您可以访问原始的Thread对象,或者可以获得该访问权限,那么最好使用Thread.Join()

Edit: Also, if this is taking place in a GUI like WinForms or WPF, you may want to consider using BackgroundWorker 编辑:另外,如果这是在WinForms或WPF等GUI中进行的,您可能需要考虑使用BackgroundWorker

The main disadvantage to using Thread.Sleep() is that you are making the decision on how long the thread will wait. 使用Thread.Sleep()的主要缺点是您正在决定线程将等待多长时间。 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. 为了达到最佳效果,您应该使用ManualResetEvent (或AutoResetEvent ),以便在依赖操作完成后立即恢复您的线程。

ManualResetEvent is definitely the way to go. ManualResetEvent绝对是最佳选择。

From the code snippet you supplied, it looks like you are delegating the execution within your Execute method. 从您提供的代码段中,您似乎在Execute方法中委派执行。 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. 您也可以同步执行该过程。

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 . 它们可能比Wait / Pulse组合,我认为你应该在这里使用它 But Manual/AutoResetEvents will be way faster than any Thread.Sleep(x) that you do, even if you choose x = 1 . 但是,即使您选择x = 1Manual/AutoResetEvents也会比您执行的任何Thread.Sleep(x)更快。 And even if you lower the Windows timer resolution to 1ms. 即使您将Windows计时器分辨率降低到1毫秒。

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. 然后一个核心将以100%旋转直到条件变为真,从其他线程中偷走时间,而不是使用它来做一些有用的事情,比如计算“愤怒的小鸟”的帧 - 或者cpu可以简单地冷却一下,延迟全球变暖的可怕影响将持续一些纳秒。

Both approaches do the same thing basically. 两种方法基本上都做同样的事情。 The while loop is little bit more explicit however, since you can specify the sleep time. 然而,while循环更明确,因为您可以指定睡眠时间。 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. 虽然我会使用XXXResetEvent类,这些类意在你工作的场景中使用。我会假设线程类现在或稍后实现,具有更强大的线程代码来处理多核处理器上的线程关联。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM