WCF Service: Asynchronous method or BackgroundWorker - c#

If some method takes a lot of time, should I implement it as asynchronous?
Or maybe use synchronous in another Thread (e.g. using BackgroundWorker)?

Asychronous calling is used when you have work items that should be handled in the background and you care when they finish
Use BackgroundWorker if you have a single task that runs in the background and needs to interact with the UI. and use it if you don't care when they finish their task. The task of marshalling data and method calls to the UI thread are handled automatically through its event-based model.
Avoid BackgroundWorker if (1) your assembly does not already reference the System.Windows.Form assembly, (2) you need the thread to be a foreground thread, or (3) you need to manipulate the thread priority.

Related

C# ThreadPool or BeginInvoke without EndInvoke

On the net there a very different opinions on how to implement a fire and forget pattern.
Some say that it is no issue to call BeginInvoke without calling EndInvoke if one has to implement a fire-and-forget pattern.
Others say it's better to create a separate ThreadPool object. My concern is about the ThreadPool initialization cost. Specifically, the the method to call does only add an object to a queue and then returns.
For this, is it "faster" to create a thread on the pool or simply to call the method synchronously? I would like to know a rough threshold of work which is more expensive than to create the thread on the pool.
Are there any documentations on this and what about exception catching on the pool and other restcritions with it?
When using the ThreadPool you do not "create the thread on the pool", you use a pre-existing Thread or wait until one comes available.
Only when many jobs are waiting the Pool will add another Thread, but then that one will be well utilized.
Even better to use Tasks (Fx4 and higher).

On which thread do Async Callbacks run?

I'm making several HttpWebRequest.BeginGetResponse calls, and in the callback method of the BeginGetResponse, I'm invoking an EventHandler. In the EventHandler, there is logic to test if the download was successful. If not, it tries to redownload the Html. I'm noticing lots of threads being generated especially when there are errors. So, on which thread do the Async Callbacks run?
Is there anyway I can invoke the EventHandler on the original thread? If that is not posible, can I invoke it on the UI thread?
Thanks!
Callbacks are made on a threadpool thread. There is no mechanism in .NET to make code run on a specific thread. That is very hard to come by, you can't just interrupt a thread while it is busy and make it run some code. That causes horrible re-entrancy problems that a lock cannot solve.
A thread must be in an idle state, not actively mutating the state of the program. There's one kind of thread that behaves that way, the UI thread in a Winforms or WPF app. That's also the thread that has to deal with objects that are fundamentally thread-unsafe, anything related to the UI. This is not a coincidence.
Both class libraries make it possible to marshal a call from a worker thread to the UI thread, specifically to help getting the UI updated in a thread-safe way. In Winforms you use Control.Begin/Invoke(), in WPF you use Dispatcher.Begin/Invoke(). BackgroundWorker is a handy class to get this done without explicitly managing the marshaling. But isn't suitable for I/O completion callbacks.
What do you mean by "on the original thread"? Which original thread? You can marshal to the UI thread using Control.BeginInvoke or Dispatcher.BeginInvoke. You can't marshal to an arbitrary thread - it has to have something like a message pump waiting for work.
As for which thread HttpWebRequest async callbacks are executed on - I would expect either a general thread pool worker thread, or possibly an IO completion port thread.
Using the Begin/End Async pattern, be aware that it's possible for many kinds of tasks to complete on the thread they were called from. When you call BeginXXX, it returns a boolean that signifies if the task was completed on the calling thread or not.
The basic answer is, it could be any thread.
If you are using WPF you can use the Dispatcher to invoke your logic on the UI thread.
Otherwise, (if not in WPF) you could use a SyncrhronizationContext to accomplish the same thing.

STAThead on a DLL for using with Task/BackgroundWorker

Good morning,
I made a simple dll in which I use a WebBrowser control to do some simple tasks. Now I want to use its methods from the main UI in a separate Task or a BackgroundWorker. The problem is that whenever I use the methods I get the "no STAThread" exception... How can I get around this? Of course, in the dll there is no Main() method and I can't either add the STAThread attribute to the constructor.
Thank you very much.
Well, to get code running in a new STA thread you should create a new thread and explicitly force it to be an STAThread using Thread.SetApartmentState before starting it. You'll then need to use Control.BeginInvoke to marshal calls back to the UI thread - you don't want to use BackgroundWorker or Task, as those will use a threadpool thread.
On the other hand, it's not clear whether that will help in this case - if you're using a WebBrowserControl you'll probably need a message loop running etc.
It's not really clear what you mean by "use its methods from the main UI". Is this WebBrowserControl part of the UI which is running in the normal UI thread? If so, you'll need to marshal to that thread from the other thread (e.g. using Control.BeginInvoke) - and the other thread doesn't need to be an STA thread for that to happen.

Making thread-safe calls to windows forms controls

The MSDN article: How to: Make Thread-Safe Calls to Windows Forms Controls
says we should use async delegate to make the call. But why does the async delegate make the call safe?
Windows controls use the Component Object Model (COM) single-threaded apartment (STA) model because those underlying controls are apartment-threaded. Furthermore, many of the controls use the message pump for many operations. This model says that all function calls to each control must be on the same thread that created the control. Invoke (and BeginInvoke and EndInvoke) marshals method calls to the proper thread.
From Bill Wagner's More Effective C#. Item 16. Understand Cross-Thread Calls in Windows Forms and WPF
You'll call control.BeginInvoke() or control.Invoke() and that method will take care of inserting your delegate in the GUI dispatch thread safely, so a bit later on your delegate will be processed and executed in the GUI thread and not the thread you'r in
The bottom line is this: You shouldn't update the UI Controls from a thread other than the one on which the control was created (UI / Main Thread). Otherwise you may see some unpredictable behavior.
If you need to update the UI from a worker thread (other than the main thread) you need to switch back to the UI Thread before updating the UI.
The article suggests using
IsInvokeRequired (which returns true if the current thread is not the one in which UI was created.) and Invoke(delegate) which runs the delegate on the correct/UI thread. This is useful when you want to update the UI in between the async process. e.g. update progress on the UI.
BackgroundWorker which executes registered handlers to its DoWork event async. on a worker thread and runs the registered handlers to its RunWorkerCompleted event on the calling thread. This is ideal if you want to update the UI with something after the async task has completed. e.g. post a Done indication on the UI
Because, windows forms controls are designed in that way, so they can be accessed only from within he thread, which owes them. And the async delegate, when used correctly, makes the call safe.
The actual answer to the given question is contained in the second paragraph of the given MSDN article =)
Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible, such as race conditions and deadlocks. It is important to make sure that access to your controls is performed in a thread-safe way.
You should check whether you can access control immediately, without indirection ( checking the InvokeRequired property ), if you can't, you should access it asynchronously ( very simplified explanation: the system will wait until it can safely access a control )

C#: Where does Control.BeginInvoke run?

What does that method do exactly? I was thinking that it maybe went out into a separate thread, but handled things like control updating on the correct thread. But now I am starting to think that it maybe just runs on the UI thread. Which means that calling BeginInvoke on a control from the UI is pretty much the same as calling Invoke? Or?
It basically adds the delegate to a queue of "tasks to execute". The UI thread runs those tasks in order.
The difference between Control.Invoke and Control.BeginInvoke is basically that Control.Invoke block the worker thread until the task has executed on the UI thread, whereas BeginInvoke doesn't. I'm not sure offhand whether there's any difference between BeginInvoke and Invoke when you call it from the UI thread.
I'm not 100% sure I get that last sentence.
It contains "from the UI...", does that mean "you call BeginInvoke from the same thread the UI is living on?" or "on a control from the UI", that is, a control which is part of the UI?
Anyway, both methods ends up running the delegate in question on the same thread the UI lives on. The difference is of course that Invoke blocks, and BeginInvoke doesn't. The blocking relates to the thread that does the calling.
Control.BeginInvoke is generally used to update the UI/Control on the thread that created the UI. UI elements have a design constraint that they can only be updated from the creating thread.
Hence to update the UI from a different (worker / threadpool) thread, you have to switch to the right thread. Control.BeginInvoke does that for you - asynchronously (in that you dont block till the delegate is executed). Invoke does the same thing except that you block till the delegate has been executed.
1st google result - WinForms UI Thread Invokes: An In-Depth Review of Invoke/BeginInvoke/InvokeRequred
Note that if you use Control.BeginInvoke to invoke a delegate that returns something, you can then use Control.EndInvoke to access the returned value. If the delegate hasn't executed yet, EndInvoke will block until it has returned.

Categories