BackgroundWorker component in services - c#

I know the BackgroundWorker should not be used in Windows Services but would anyone have a good online reference explaining why?

BackgroundWorker relies on a current SynchronizationContext being set in order to function. It's really intended and designed specifically for working with UI code.
It's typically better in a service to self-manage your threads, since there are no UI synchronization issues. Using the threading API (or .NET 4 Task API) is a much better option here.

Well, it's okayish to use a BGW in a service, it just doesn't do anything especially useful. Its reason for being is its ability to raise the ProgressChanged and RunWorkerCompleted events on a specific thread. Getting code to run on a specific thread is a very non-trivial thing to do. You cannot simply inject a call into the thread while it is executing code. That causes horrible re-entrancy problems. The thread has to be 'idle', in a state where inject code doesn't cause trouble.
Having a thread in an idle state is a fairly unnatural condition. You use threads to run code, not for them to be idly spinning its heels. This is however the way a UI thread works. It spends 99% of its time in the message loop, waiting for Windows to tell it to do something. A button click, a paint request, a keyboard press, that sort of thing. While it is inside the message loop, it is in fact idle. A very good time to execute injected code.
Which is what Winforms' Control.Begin/Invoke and WPF's Dispatcher.Begin/Invoke do. They put a delegate in a queue, the queue is emptied and the delegate targets executed by the message loop. The WindowsFormsSynchronizationContext and DispatcherSynchronizationContext classes are the synchronization providers that uses them. Winforms and WPF replace SynchronizationContext.Current with an instance of them. Which in turn gets used by BGW to raise the events. Which makes them run on the UI thread. Which allows you to update the non thread-safe user interface components from a worker thread.
You can probably see where this is heading, a service uses neither. The default synchronization provider doesn't synchronize anything. It simply uses a threadpool thread to call the Send or Post callback. Which is what will happen when you use BGW in a service. Now there is actually no point at all in having these events. You might as well let the DoWork handler call the event handling methods directly. After all, the thread on which DoWork runs is just another threadpool thread as well.
Well, no real harm done, other than making it quite a bit slower.

I've used BackgroundWorker in windows services many times without any ill effect. While its use of SynchronizationContext may be unnecessary, I haven't observed it causing problems or poor performance.

Related

Other ways to update UI from thread in C#

My application is heavily depended on threads to do the complex processing of very large data. The UI needs to be updated as the processing is being done. I know and tried to used BackgroundWorker's OnProgressChanged and RunWorkerCompleted methods to update the UI. Also using Invoke method of the UI thread to update. Everything seems to work fine on Win XP 32 bit and 64 bit OS. On Win Vista and Win 7 (32 and 64 bit), the application randomly hangs while updating the UI by using Invoke method.
Does the behavior of Invoke changes on different Win OS?
What are the other ways of updating UI from thread apart from Invoke?
Thanks
Does the behavior of Invoke changes on different Win OS?
It should not, no. But, threading problems can materialize in very unpredictable ways. It is possible that you have an unidentified problem.
What are the other ways of updating UI from thread apart from Invoke?
Using Invoke or BeginInvoke are way overused especially when trying to report simple progress information to the UI thread. If you search for some of my answers related to the subject you will see that I rip on this approach all of the time. And for good reason since their are many disadvantages to using this technique. It is unfortunate that BackgroundWorker uses this mechanism exclusively for updating the UI through its ProgressChanged event.
One alternate method is to have your worker thread publish progress information into a shared variable and have the UI thread poll for it periodically via a timer. Here are some of my usual talking points in justifying this approach over the marshaling techniques.
Invoke and BeginInvoke are expensive operations.
The UI thread gets to dictate when and how often to update the form and its controls.
It eliminates the tight coupling between UI and worker threads that ISynchronizeInvoke imposes.
There is no risk of overrunning or saturating the UI message queue with a bunch of marshaling operations.
You get more throughput on the worker thread since it does not have to wait for response as would be the case with Invoke.
Not sure what's going wrong, but you could always just have a System.Windows.Forms.Timer running that updates the GUI periodically; use some member variables to pass raw data between threads, inside locks if necessary. Not the most elegant solution, but it might give you a different perspective into what's hanging since the threads are more independent this way, rather than relying on a background thread to Invoke your main thread.
You could try using one of the Invoke() or BeginInvoke() overloads that takes a Dispatcher.Priority enum as a parameter. If you select a parameter such as 'Background' you should see your application is still responsive. The only issue then becomes ensuring you are servicing your incoming data at an adequate rate without an ever increasing queue.
Another option would be to forego the multithreading entirely. If your long-running operation can be broken up into chunks, do it in the GUI thread and use Application.DoEvents() when you want to update the GUI.
I used to dislike use of that method since it could not only update the GUI but also start responding to user input, kicking off timers, etc., but ultimately it's no less safe than using a background thread, which allows the GUI to start doing anything at any time. So probably after each call of Application.DoEvents() you'd need to check _canceled or whatever. (I eventually decided I dislike the existence of this method, since it eliminates the guarantees of linear execution order, than the use of it).
Of course you lose multicore support this way, so it'd affect performance if you're trying to run lots of background ops at the same time.

Are there alternatives to invoke in WPF when passing data from a different thread?

I know how to pass data from a worker thread to the main thread via Invoke/BeginInvoke.
I can also pull from a thread safe collection with a timer from the main thread.
I prefer using tasks (Task.Factory.StartNewTask()) and using Backgroundworker with them seams a bit clumsy.
Sometimes the gui is a bit laggy which is due to (Begin)Invoke I assume.
Pulling with a timer also doesn't feel like the right way.
Creating a new Backgroundworker for each new task seams also strange.
Are there any other possibilities?
In .NET, memory is shared within an AppDomain, which means all threads can access all data. So, what you're actually doing is controlling access to particular bits of data from particular threads so they don't interfere with each other.
Invoke and BeginInvoke allow you to run code on the UI thread, which is useful because UI controls can only be accessed from the UI thread. BackgroundWorker is another solution, as is SynchronizationContext.
However, they all work by sending known windows messages to the UI message loop. If you call Invoke too often, you send too many messages and the UI thread is swamped which makes the UI "a bit laggy".
If this happens, you must slow down the rate that messages are sent. There are a couple of ways to do this:
1) Call Invoke less frequently: this means waiting for bigger "chunks" of state changes in your background thread before it calls Invoke to update the UI.
2) Use a UI Timer: there is no point in trying to update the UI faster than the human eye can detect. A UI Timer also sends windows messages to the UI message loop, but at a known rate. The Tick handler can then pull the necessary data from shared memory to update the UI.
Both approaches have their strengths and weaknesses. The choice really depends on how easy it is to group state changes in the background thread into bigger chunks, while making sure the UI doesn't miss any state changes.

What's wrong with calling Invoke, regardless of InvokeRequired?

I've seen the common setup for cross threading access to a GUI control, such as discussed here:
Shortest way to write a thread-safe access method to a windows forms control
All the web hits I found describe a similar thing.
However, why do we need to check InvokeRequired? Can't we just call Invoke directly?
I assume the answer is no, so my real question is 'why'?
From non-UI threads we can't touch the UI - very bad things can happen, since controls have thread affinity. So from a non-UI thread we must (at a minumum) call Invoke or BeginInvoke.
For UI-threads, however - we don't want to call Invoke lots of time; the issue is that if you are already on the UI thread, it still has the unnecessary overhead of sending a message to the form's pump and processing it.
In reality, in most threading code you know you expect a specific method to be called on a non-UI thread, so in those cases, there is no additional overhead: just call Invoke.
If you try to invoke before a window handle is created (for example, when calling form constructor), you will get an InvalidOperationException. So, generally InvokeRequired check is required.
See MSDN for details.
InvokeRequired basically tells you if you're executing on the right thread or not. If you're not on the correct thread, you need to marshal the task to the correct thread otherwise you don't. Hence the need for the check.
The issue is that GUI controls have a requirement that only code executing on the same thread that was used to instantiate the GUI control can access the GUI control. The reasons behind this requirement are tied to the way that Windows is architected. Suffice to say, it would very difficult to change this.
The InvokeRequired checks the identity of the current executing thread against the identity of the instantiating thread. If they are the same, the code can freely interact with the control. If not, the code must marshal the data across from the current thread to the instantiating thread. This is a slow and costly process and is to be avoided if at all possible. Your code will work if you always invoke and it may be that you will not notice the performance hit, but this scenario is going to be increasingly common as multi-core systems come into use. It is best not to create code "knots" that have to be undone later.
One reason I can think of is performence.
If most of the time the calling thread is the same as the creating thread then you'll have some unnessecry overhead.
The Invoke is going to call the code through Delegate and not directly which would be costly.
Its cost effective to call Invoke only when it required. Hence, InvokeRequired is used to find out is the call being made from same thread or another thread?

How do I Yield to the UI thread to update the UI while doing batch processing in a WinForm app?

I have a WinForms app written in C# with .NET 3.5. It runs a lengthy batch process. I want the app to update status of what the batch process is doing. What is the best way to update the UI?
The BackgroundWorker sounds like the object you want.
The quick and dirty way is using Application.DoEvents() But this can cause problems with the order events are handled. So it's not recommended
The problem is probably not that you have to yield to the ui thread but that you do the processing on the ui thread blocking it from handling messages. You can use the backgroundworker component to do the batch processing on a different thread without blocking the UI thread.
Run the lengthy process on a background thread. The background worker class is an easy way of doing this - it provides simple support for sending progress updates and completion events for which the event handlers are called on the correct thread for you. This keeps the code clean and concise.
To display the updates, progress bars or status bar text are two of the most common approaches.
The key thing to remember is if you are doing things on a background thread, you must switch to the UI thread in order to update windows controls etc.
To beef out what people are saying about DoEvents, here's a description of what can happen.
Say you have some form with data on it and your long running event is saving it to the database or generating a report based on it. You start saving or generating the report, and then periodically you call DoEvents so that the screen keeps painting.
Unfortunately the screen isn't just painting, it will also react to user actions. This is because DoEvents stops what you're doing now to process all the windows messages waiting to be processed by your Winforms app. These messages include requests to redraw, as well as any user typing, clicking, etc.
So for example, while you're saving the data, the user can do things like making the app show a modal dialog box that's completely unrelated to the long running task (eg Help->About). Now you're reacting to new user actions inside the already running long running task. DoEvents will return when all the events that were waiting when you called it are finished, and then your long running task will continue.
What if the user doesn't close the modal dialog? Your long running task waits forever until this dialog is closed. If you're committing to a database and holding a transaction, now you're holding a transaction open while the user is having a coffee. Either your transaction times out and you lose your persistence work, or the transaction doesn't time out and you potentially deadlock other users of the DB.
What's happening here is that Application.DoEvents makes your code reentrant. See the wikipedia definition here. Note some points from the top of the article, that for code to be reentrant, it:
Must hold no static (or global) non-constant data.
Must work only on the data provided to it by the caller.
Must not rely on locks to singleton resources.
Must not call non-reentrant computer programs or routines.
It's very unlikely that long running code in a WinForms app is working only on data passed to the method by the caller, doesn't hold static data, holds no locks, and calls only other reentrant methods.
As many people here are saying, DoEvents can lead to some very weird scenarios in code. The bugs it can lead to can be very hard to diagnose, and your user is not likely to tell you "Oh, this might have happened because I clicked this unrelated button while I was waiting for it to save".
Use Backgroundworker, and if you are also trying to update the GUI thread by handling the ProgressChanged event(like, for a ProgressBar), be sure to also set WorkerReportsProgress=true, or the thread that is reporting progress will die the first time it tries to call ReportProgress...
an exception is thrown, but you might not see it unless you have 'when thrown' enabled, and the output will just show that the thread exited.
Use the backgroundworker component to run your batch processing in a seperate thread, this will then not impact on the UI thread.
I want to restate what my previous commenters noted: please avoid DoEvents() whenever possible, as this is almost always a form of "hack" and causes maintenance nightmares.
If you go the BackgroundWorker road (which I suggest), you'll have to deal with cross-threading calls to the UI if you want to call any methods or properties of Controls, as these are thread-affine and must be called only from the thread they were created on. Use Control.Invoke() and/or Control.BeginInvoke() as appropriate.
If you are running in a background/worker thread, you can call Control.Invoke on one of your UI controls to run a delegate in the UI thread.
Control.Invoke is synchronous (Waits until the delegate returns). If you don't want to wait you use .BeginInvoke() to only queue the command.
The returnvalue of .BeginInvoke() allows you to check if the method completed or to wait until it completed.
Application.DoEvents() or possibly run the batch on a separate thread?
DoEvents() was what I was looking for but I've also voted up the backgroundworker answers because that looks like a good solution that I will investigate some more.

Best way to make events asynchronous in C#

Events are synchronous in C#. I have this application where my main form starts a thread with a loop in it that listens to a stream. When something comes along on the stream an event is fired from the loop to the main form.
If the main form is slow or shows a messagebox or something the loop will be suspended. What is the best way around this? By using a callback and invoke on the main form?
Since you're using a form, the easier way is to use the BackgroundWorker component.
The BackgroundWorker class allows you
to run an operation on a separate,
dedicated thread. Time-consuming
operations like downloads and database
transactions can cause your user
interface (UI) to seem as though it
has stopped responding while they are
running. When you want a responsive UI
and you are faced with long delays
associated with such operations, the
BackgroundWorker class provides a
convenient solution.
Hmmm, I've used different scenarios that depended on what I needed at the time.
I believe the BeginInvoke would probably be the easiest to code since you're almost there. Either way you should be using Invoke already, so just changing to BeginInvoke. Using a callback on a separate thread will accomplish the same thing (as long as you use the threadpool to queue up the callback) as using BeginInvoke.
Events are just delegates, so use BeginInvoke. (see Making Asynchronous Method Calls in the .NET Environment)
You have a few options, as already detailed, but in my experience, you're better off leaving delegates and BeginInvoke, and using BackgroundWorker instead (v2.0+), as it is easier to use and also allows you to interact with the main form on the thread's completion. All in all a very weel implemented solution, I have found.
System.ComponentModel.BackgroundWorker is indeed a good starting point. It will do your asynchronous work, give you notifications of important events, and has ways to better integrate with your forms.
For example, you can activate progress notifications by registering a handler for the ProgressChanged event. (which is highly recommended if you have a long, asynchronous process and you don't want your user to think the application froze)

Categories

Resources