To make a choice between ManualResetEvent or Thread.Sleep()
Asked Answered
R

7

9

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...

Rillis answered 4/11, 2009 at 19:6 Comment(2)
Just want to point out Thread.Sleep(0) usage. Specify zero (0) to indicate that this thread should be suspended to allow other waiting threads to execute. In this case Sleep(0) is better than Sleep(1000), but using WaitHandle is still more appropriate though.Gudren
The empty while loop is basically a spinwait- it will completely consume a CPU. Not recommended.Femme
B
16

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).

Botticelli answered 4/11, 2009 at 19:25 Comment(2)
read somewher tht manual resets work in kernel mode...if so then there should be a performance overhead, right? PS: I've edited the question again...Rillis
You suggest going with the OS primitive, but you really should explain why.Initiatory
F
4

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.

Femme answered 4/11, 2009 at 19:10 Comment(2)
But arent' manualResetevents expensive when compared to the other construct. I use .net 2.0. Read somewhere tht manual resets work in kernel mode where as its monitor alternatives work in user mode...so extra overhead due change of mode...! Is this true?Rillis
They are more expensive to create than Monitors, but they're also more fully featured. It depends on how frequently you're creating them. If you're looking to run thousands of these a second, a lighter-weight approach would be better.Femme
Y
2

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

Youngs answered 4/11, 2009 at 19:9 Comment(2)
Then use ManualResetEvent as @Femme suggests. Or find a way to get that Thread. The only drawback with using ManualResetEvent is that both the caller and the worker have to use it, creating a possibly unwanted dependency.Youngs
@Randolpho. Wouldn't both methods have to share resource to be able to signal each other? In the case of the while loop both threads have to know about the 'JobCompleted' boolean.Leitman
K
2

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.

Koressa answered 4/11, 2009 at 19:12 Comment(0)
T
1

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.

Tonedeaf answered 4/11, 2009 at 19:33 Comment(0)
R
1

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.

Runthrough answered 23/8, 2013 at 8:10 Comment(0)
L
0

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.

Leitman answered 4/11, 2009 at 19:18 Comment(1)
A ManualResetEvent behaves quite differently than periodically polling.Holler

© 2022 - 2024 — McMap. All rights reserved.