5 Replies - 12804 Views - Last Post: 23 December 2011 - 02:46 AM Rate Topic: -----

#1 darek9576  Icon User is offline

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,682
  • Joined: 13-March 10

Threading - BackgroundWorker vs Thread

Posted 25 November 2011 - 10:22 AM

I know that .NET is moving towards Threading.Tasks but i have not got a chance to get to know that. So far, i have been playing with Thread class and Background worker (i dont know whether they are still widely used but thought i would learn them anyway for a good overview of threading in C#).

Question is:

When i do the same task using Thread and BW - let say, im reading a long file into a string.

string contentsOfFile = streamReadInstance.ReadToEnd();



Now, i know that we cannot use different thread than UI thread to update a Winform so why when i use the thread instance i get the error but when i do

 ..... BW_RunWorkerCompleted....
{
     richtextboxInstance.Text = contentsOfFile;
}



its fine. Is the BackgroundWorker a "special kind of thread" designed to make working with winforms easier so that we dont have to bother with Invokerequired etc.

Thanks for any explanation.

Is This A Good Question/Topic? 0
  • +

Replies To: Threading - BackgroundWorker vs Thread

#2 Martyr2  Icon User is offline

  • Programming Theoretician
  • member icon

Reputation: 4318
  • View blog
  • Posts: 12,100
  • Joined: 18-April 07

Re: Threading - BackgroundWorker vs Thread

Posted 25 November 2011 - 11:34 AM

Quote

Now, i know that we cannot use different thread than UI thread to update a Winform


You can, you just have do it through a delegate... or in the case of a background worker it is recommended to do it through "ProgressChanged" or "RunWorkerCompleted" events for a BackgroundWorker class.

For instance you can start a background worker that processes your file in the background on a separate thread. As time goes on, it will fire ProgressChanged events which you can then use to update a progress bar on your GUI. The one thing you don't want to be doing is writing code in its "DoWork" event that manipulates the interface.

The BackgroundWorker class is essentially a wrapper class for a thread. It manages a separate dedicated thread and exposes some nice functionality methods.

Threads themselves are a bit more raw in that it expects you do handle the delegation and event handling a bit more. You can have a thread update the winform as well, but here you have to use a delegate (think of them as a pointer to a function... event handlers are types of delegates that when a delegate is called it passes control to your Button1_onclick function).

I can only assume you are using the thread class wrong if you are getting an error. If you show us how you are attempting to use a thread as opposed to a BackgroundWorker perhaps we can tell you more about the differences in what you are trying to do.

:)
Was This Post Helpful? 1
  • +
  • -

#3 darek9576  Icon User is offline

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,682
  • Joined: 13-March 10

Re: Threading - BackgroundWorker vs Thread

Posted 25 November 2011 - 11:45 AM

I am not coding anything in particular, im just playing with code to learn new things so have nothing to show you im afraid.

Yes, i was aware that you can update UI through a thread but you have to use InvokeRequired to compare thread IDs. (i think thats right).

And about the point that a Thread class is a bit "raw" i agree 100%.

Thanks for the answer. Informative as always.
Was This Post Helpful? 0
  • +
  • -

#4 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 991
  • View blog
  • Posts: 971
  • Joined: 30-September 10

Re: Threading - BackgroundWorker vs Thread

Posted 25 November 2011 - 01:55 PM

You actually missed a very important alternative. The ThreadPool class. That class should be preferred over the Thread class in many situations.

The Thread class is heavy duty. It always creates a brand new thread, of which then has to be destroyed once the operation has completed. It is very expensive.

The ThreadPool class uses the CLR thread pool, and is often the more efficient way to thread your applications. Threads are pooled, and thus reused, so the overhead of creating and destroying threads is managed in a much more efficient way.

So, I would say you should use the Thread class when you need to run a long running operation on another thread, or when you need functionality that can only be obtained by using the Thread class (like being able to set thread priorities, for example).


Moving on, the BackgroundWorker class doesn't create a dedicated thread. It uses the thread pool, via the BeginInvoke() method to invoke your work on a thread pool thread.

The BackgroundWorker class uses the event based asynchronous pattern, and technically should only be used for compute bound work, if we are being technically correct. It is not special in it's use of threads at all. It just pulls a thread from the thread pool, just like the Task class does, and just like the ThreadPool class does.

How it is a bit special, is in the way it handles switching between synchronization contexts so you don't have to use Invoke() to perform UI updates. It does this by using the AsyncOperation class.

It uses the AsyncOperationManager.CreateOperation(null); method call to get an AsyncOperation instance, of which encapsulates the current synchronization context. It does this just before queuing the delegate for execution on a thread pool thread, so the 'captured context' will be the calling context, which will be the form's context. It stores this indirect reference to the form's context for later use...

It then performs the work in your DoWork handler method on the thread pool thread, and once the work has finished executing, it calls PostOperationCompleted() on the AsyncOperation instance, passing in a delegate to execute.

This delegate encapsulating your RunWorkerCompleted handler method is 'posted back' to the context that the AsyncOperation is encapsulating, which is, of course, the form's context. This results in your RunWorkerCompleted handler method being called on the original calling thread (i.e. the UI thread), just as if you never created the second thread :)

For the progress reporting side, it uses Post() to execute the progress reporting delegate on the captured context in a very similar way..

Examples of using the AsyncOperation and ThreadPool classes are given in my C# Multi-Threading In A GUI Environment tutorial


This is opposed to the Thread class, with which you are essentially dealing with a CLR thread directly, with no automatic help from the framework with regards to marshaling back to calling threads. It is at a noticeably lower level of abstraction than the BackgroundWorker class, let's say :)

EDIT:

Quote

you have to use InvokeRequired to compare thread IDs. (i think thats right).


.InvokeRequired does compared the thread IDs, yes. However, you don't have to use it (but often you should when using Control.Invoke/BeginInvoke(), you can just call BeginInvoke/Invoke()) without checking .InvokeRequired if you know that you are always off the UI thread in a particular piece of code, for example.

Generally, I aim to avoid using manual invoking like that though these days :)

This post has been edited by CodingSup3rnatur@l-360: 13 July 2012 - 08:15 AM

Was This Post Helpful? 4
  • +
  • -

#5 globus25  Icon User is offline

  • New D.I.C Head

Reputation: -3
  • View blog
  • Posts: 19
  • Joined: 07-July 11

Re: Threading - BackgroundWorker vs Thread

Posted 22 December 2011 - 05:27 PM

Without any theoretical approach I only saw that backgroungworker is better when U forceably close the application :) and normal thread will still be open after force shut down of program
Was This Post Helpful? 0
  • +
  • -

#6 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 991
  • View blog
  • Posts: 971
  • Joined: 30-September 10

Re: Threading - BackgroundWorker vs Thread

Posted 23 December 2011 - 02:46 AM

That's because CLR thread pool threads (which the BackgroundWorker uses) are always background threads, and so allow the app domain to be unloaded immediately. The CLR just terminates all background threads, whether they are finished or not.

Threads started with the Thread class however, are foreground threads by default, and the app domain cannot be unloaded until all foreground threads have completed. The CLR doesn't forcibly terminate the foreground threads you create, it allows them to complete. Thus, you can easily end up with a situation where you application doesn't terminate when the user tells it to, as your foreground thread is keeping the application alive.

However, the Thread class has a property called IsBackground which determines whether the thread is foreground or background. If you set that to true, the thread becomes a background thread, and will now allow your application to terminate immediately, on request.

This is one of the reasons you may need to use the Thread class over the ThreadPool class; if you need to create foreground threads.

This post has been edited by CodingSup3rnatur@l-360: 13 July 2012 - 08:25 AM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1