BackgroundWorker vs background Thread

.NetWinformsMultithreadingBackgroundworker

.Net Problem Overview


I have a stylistic question about the choice of background thread implementation I should use on a windows form app. Currently I have a BackgroundWorker on a form that has an infinite (while(true)) loop. In this loop I use WaitHandle.WaitAny to keep the thread snoozing until something of interest happens. One of the event handles I wait on is a "StopThread" event so that I can break out of the loop. This event is signaled when from my overridden Form.Dispose().

I read somewhere that BackgroundWorker is really intended for operations that you don't want to tie up the UI with and have an finite end - like downloading a file, or processing a sequence of items. In this case the "end" is unknown and only when the window is closed. Therefore would it be more appropriate for me to use a background Thread instead of BackgroundWorker for this purpose?

.Net Solutions


Solution 1 - .Net

Some of my thoughts...

  1. Use BackgroundWorker if you have a single task that runs in the background and needs to interact with the UI. The task of marshalling data and method calls to the UI thread are handled automatically through its event-based model. Avoid BackgroundWorker if...
    • your assembly does not have or does not interact directly with the UI,
    • you need the thread to be a foreground thread, or
    • you need to manipulate the thread priority.
  2. Use a ThreadPool thread when efficiency is desired. The ThreadPool helps avoid the overhead associated with creating, starting, and stopping threads. Avoid using the ThreadPool if...
    • the task runs for the lifetime of your application,
    • you need the thread to be a foreground thread,
    • you need to manipulate the thread priority, or
    • you need the thread to have a fixed identity (aborting, suspending, discovering).
  3. Use the Thread class for long-running tasks and when you require features offered by a formal threading model, e.g., choosing between foreground and background threads, tweaking the thread priority, fine-grained control over thread execution, etc.

Solution 2 - .Net

From my understanding of your question, you are using a BackgroundWorker as a standard Thread.

The reason why BackgroundWorker is recommended for things that you don't want to tie up the UI thread is because it exposes some nice events when doing Win Forms development.

Events like RunWorkerCompleted to signal when the thread has completed what it needed to do, and the ProgressChanged event to update the GUI on the threads progress.

So if you aren't making use of these, I don't see any harm in using a standard Thread for what you need to do.

Solution 3 - .Net

Pretty much what Matt Davis said, with the following additional points:

For me the main differentiator with BackgroundWorker is the automatic marshalling of the completed event via the SynchronizationContext. In a UI context this means the completed event fires on the UI thread, and so can be used to update UI. This is a major differentiator if you are using the BackgroundWorker in a UI context.

Tasks executed via the ThreadPool cannot be easily cancelled (this includes ThreadPool. QueueUserWorkItem and delegates execute asyncronously). So whilst it avoids the overhead of thread spinup, if you need cancellation either use a BackgroundWorker or (more likely outside of the UI) spin up a thread and keep a reference to it so you can call Abort().

Solution 4 - .Net

Also you are tying up a threadpool thread for the lifetime of the background worker, which may be of concern as there are only a finite number of them. I would say that if you are only ever creating the thread once for your app (and not using any of the features of background worker) then use a thread, rather than a backgroundworker/threadpool thread.

Solution 5 - .Net

You know, sometimes it's just easier to work with a BackgroundWorker regardless of if you're using Windows Forms, WPF or whatever technology. The neat part about these guys is you get threading without having to worry too much about where you're thread is executing, which is great for simple tasks.

Before using a BackgroundWorker consider first if you wish to cancel a thread (closing app, user cancellation) then you need to decide if your thread should check for cancellations or if it should be thrust upon the execution itself.

BackgroundWorker.CancelAsync() will set CancellationPending to true but won't do anything more, it's then the threads responsibility to continually check this, keep in mind also that you could end up with a race condition in this approach where your user cancelled, but the thread completed prior to testing for CancellationPending.

Thread.Abort() on the other hand will throw an exception within the thread execution which enforces cancellation of that thread, you must be careful about what might be dangerous if this exception was suddenly raised within the execution though.

Threading needs very careful consideration no matter what the task, for some further reading:

Parallel Programming in the .NET Framework Managed Threading Best Practices

Solution 6 - .Net

I knew how to use threads before I knew .NET, so it took some getting used to when I began using BackgroundWorkers. Matt Davis has summarized the difference with great excellence, but I would add that it's more difficult to comprehend exactly what the code is doing, and this can make debugging harder. It's easier to think about creating and shutting down threads, IMO, than it is to think about giving work to a pool of threads.

I still can't comment other people's posts, so forgive my momentary lameness in using an answer to address piers7

Don't use Thread.Abort(); instead, signal an event and design your thread to end gracefully when signaled. Thread.Abort() raises a ThreadAbortException at an arbitrary point in the thread's execution, which can do all kinds of unhappy things like orphan Monitors, corrupt shared state, and so on.
http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

Solution 7 - .Net

I want to point out one behavior of BackgroundWorker class that wasn't mentioned yet. You can make a normal Thread to run in background by setting the Thread.IsBackground property.

> Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. [1]

You can test this behavoir by calling the following method in the constructor of your form window.

void TestBackgroundThread()
{
    var thread = new Thread((ThreadStart)delegate()
    {
        long count = 0;
        while (true)
        {
            count++;
            Debug.WriteLine("Thread loop count: " + count);
        }
    });

    // Choose one option:
    thread.IsBackground = true; // <--- This will make the thread run in background
    thread.IsBackground = false; // <--- This will delay program termination

    thread.Start();
}

When the IsBackground property is set to true and you close the window, then your application will terminate normaly.

But when the IsBackground property is set to false (by default) and you close the window, then just the window will disapear but the process will still keep running.

The BackgroundWorker class utilize a Thread that runs in the background.

Solution 8 - .Net

If it ain't broke - fix it till it is...just kidding :)

But seriously BackgroundWorker is probably very similar to what you already have, had you started with it from the beginning maybe you would have saved some time - but at this point I don't see the need. Unless something isn't working, or you think your current code is hard to understand, then I would stick with what you have.

Solution 9 - .Net

The basic difference is, like you stated, generating GUI events from the BackgroundWorker. If the thread does not need to update the display or generate events for the main GUI thread, then it can be a simple thread.

Solution 10 - .Net

A background worker is a class that works in a separate thread, but it provides additional functionality that you don't get with a simple Thread (like task progress report handling).

If you don't need the additional features given by a background worker - and it seems you don't - then a Thread would be more appropriate.

Solution 11 - .Net

What's perplexing to me is that the visual studio designer only allows you to use BackgroundWorkers and Timers that don't actually work with the service project.

It gives you neat drag and drop controls onto your service but... don't even try deploying it. Won't work.

Services: Only use System.Timers.Timer System.Windows.Forms.Timer won't work even though it's available in the toolbox

Services: BackgroundWorkers will not work when it's running as a service Use System.Threading.ThreadPools instead or Async calls

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionfreddy smithView Question on Stackoverflow
Solution 1 - .NetMatt DavisView Answer on Stackoverflow
Solution 2 - .NetParmesanCodiceView Answer on Stackoverflow
Solution 3 - .Netpiers7View Answer on Stackoverflow
Solution 4 - .NetMattView Answer on Stackoverflow
Solution 5 - .NetBrett RyanView Answer on Stackoverflow
Solution 6 - .Netajs410View Answer on Stackoverflow
Solution 7 - .NetDoomjunkyView Answer on Stackoverflow
Solution 8 - .NetGandalfView Answer on Stackoverflow
Solution 9 - .NetDavid R TribbleView Answer on Stackoverflow
Solution 10 - .NetCesarView Answer on Stackoverflow
Solution 11 - .NetscottweedenView Answer on Stackoverflow