views:

491

answers:

4

Hi, I have an application that grabs a snapshot of another desktop. This process is placed and run asynchronously in a separate backgroundworker thread. Tiny mockup of the DoWork event is:

private void GrabImage_DoWork(object sender, DoWorkEventArgs e)
{
 /*Grab the image..*/
 System.Threading.Thread.Sleep(10)
}

Currently there was placed a thread.sleep(10) and I am just wondering whether such a small sleep will actually render the performance poor due to constant additional unneeded context switches.

Let me know if the question requires further explanation. Cheers,

EDIT: Decided to throw a bunch of more context in to help focus on a specific answer.

Issues brought up Q: Is this the only background thread currently running? A: No. There is in fact a few backgroundworker threads as well as a thread which queues up multiple threads using the .NET Threadpool class. Therefore the sleep was originally placed into the code for the thought of allowing a context switch to occur for these other threads. However I am lead to believe that anyways the OS is time sliced so that I'm sure without the sleep the other threads will get a chance to execute?

Q: Is this background worker constantly running? A: The application provides an interface to interact with the desktop with a toggle button to display the background image. Therefore the backgroundworker can essentially be off or constantly churning if the button is toggled.

I hope the overall question doesn't seem overall unimportant to performance. I am trying to find a good balance between performance and usability.

+1  A: 

It absolutely could but it all depends on the context within which this code is executed. The best way to answer your question is to profile the application to see if this code creates bottlenecks.

Andrew Hare
I've never done any profiling.Is there a nice guide/tutorial on this you may recommend.
Setheron
Check out this link http://www.red-gate.com/products/ants_performance_profiler/index.htm. While Regate's ANTS may cost money it really is a excellent profiler and their website has may walkthroughs that should get you started.
Andrew Hare
A: 

Using Sleep:

  • May increase total CPU time (because of the overhead required to go to sleep and to wake up)
  • Will increase the task's wall/clock time (because of going to sleep even when not necessary)

An alternative may be to use a lower-priority thread instead of sleeps.

ChrisW
+3  A: 

The sleep will potentially cause extra context switching, since it will allow other threads to execute within your process.

However, it sounds like you have a single background worker thread. If that's the case, you probably are going to get context switching anyways. This tends to happen any time background workers reports progress (since they're invoking across threads) as well. With one, I doubt you'll notice the performance hit involved, although the only way to tell for sure would be to profile your application.

My bigger question would be: Why are you adding this Sleep in here in the first place, especially if it's something you're worried about. Typically, you'd add a sleep in here specifically to allow other threads to work, which often results in a context switch. If you're doing this by design, then it's not something to worry about. If you don't need this Sleep, on the other hand, there's no reason to include it.


Edit: Here are some specifics in reply to your edit:

Q: Is this the only background thread currently running? A: No. There is in fact a few backgroundworker threads as well as a thread which queues up multiple threads using the .NET Threadpool class. Therefore the sleep was originally placed into the code for the thought of allowing a context switch to occur for these other threads. However I am lead to believe that anyways the OS is time sliced so that I'm sure without the sleep the other threads will get a chance to execute?

The OS will time slice, but (by default) this thread will have a default priority. It should, in theory, get as much of the processor time as your main thread and other threads running. You don't have to sleep, but there are times when this is advantageous (see below).

Q: Is this background worker constantly running? A: The application provides an interface to interact with the desktop with a toggle button to display the background image. Therefore the backgroundworker can essentially be off or constantly churning if the button is toggled.

If the worker thread is going to be sitting in a loop and just constantly eating CPU, it's usually advantageous to add some mechanism to prevent it from using up the entire CPU core (unless you need real-time performance in that thread). A small sleep (although Sleep(0) works just as well for this) is an easy option. However, it's often better, if the algorithm makes sense for this, to put some type of WaitHandle in place so you're only working as needed. This really depends on the algorithm.

Since I am already using the Threadpool class, is to queue this workload as well onto the threadpool class instead of a sepearte backgroundworker.

The BackgroundWorker class uses a ThreadPool thread, so there isn't a real advantage to doing this. BackgroundWorker makes it much simpler to work against a UI thread, however, so if you're displaying your progress on the UI, it's probably easier to do this with a BW, as you're doing now.

Reed Copsey
I edited the original post and provided hopefully some additional meaningful notes based on your response.
Setheron
I just replied to each of your edits.
Reed Copsey
Very helpful.Didn't know Backgroundworker uses a threadpool thread.
Setheron
A: 

Why is it necessary to sleep? If you make the thread only sleep once to synchronize, the synchronization mechanism will be unpredicatble, and should be made more robust to tolerate large variance in network latency.

All calls to Thread.Sleep(int) result in a context switch. Since Windows is a desktop computing OS, the scheduling granularity is pretty fine to boost perceived responsiveness, however the rule-of-thumb ~10-20 ms is pretty long.

If the snapshot grabbing method is not run very often, this will have no performance overhead at all, and rather allow the rest of the system to remain responsive, since you yield CPU time other threads that are ready to run. If you don't want to yield your CPU slice, use Thread.SpinWait(int) instead. For repeatedly calling Thread.Sleep(int) to wait for another operation to complete, I recommend using a sleep interval of at least 20 ms to ensure the other thread/process actually gets time to finish its work.

Cecil Has a Name