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.
Related
I'm building a WPF application. I'm doing some async communication with the server side, and I use event aggregation with Prism on the client. Both these things results in new threads to be spawned which are not the UI thread. If I attempt to do "WPF operations" on these callback and event handler threads the world will fall apart, which it now has started doing.
First I met problems trying to create some WPF objects in the callback from server. I was told that the thread needed to run in STA mode. Now I'm trying to update some UI data in a Prism event handler, and I'm told that:
The caller cannot access this thread because a different thread owns it.
So; what's the key to getting things right in WPF? I've read up on the WPF Dispatcher in this MSDN post. I'm starting to get it, but I'm no wizard yet.
Is the key to always use Dispatcher.Invoke when I need to run something which I'm not sure will be called on the UI thread?
Does it matter if it actually was called on the UI thread, and I do Dispatcher.Invoke anyway?
Dispatcher.Invoke = synchronously. Dispathcher.BeginInvoke = async?
Will Dispatcher.Invoke request the UI thread, and then stop to wait for it? Is it bad practice and risk of less responsive programs?
How do I get the dispatcher anyway? Will Dispatcher.CurrentDispatcher always give me the dispatcher representing the UI thread?
Will there exist more than one Dispatcher, or is "Dispatcher" basically the same as the UI thread for the application?
And what's the deal with the BackgroundWorker? When do I use this instead? I assume this is always async?
Will everything that runs on the UI thread (by being Invoked) be run in STA apartment mode? I.e. if I have something that requires to be run in STA mode - will Dispatcher.Invoke be sufficient?
Anyone wanna clearify things for me? Any related recommendations, etc? Thanks!
Going over each of your questions, one by one:
Not quite; you should only invoke onto the UI thread when necessary. See #2.
Yes, it does matter. You should not just automatically Invoke everything. The key is to only invoke onto the UI thread if necessary. To do this, you can use the Dispatcher.CheckAccess method.
That is correct.
Also correct, and yes, you do run the risk of less responsive programs. Most of the time, you are not going to be looking at a severe performance hit (we're talking about milliseconds for a context switch), but you should only Invoke if necessary. That being said, at some points it is unavoidable, so no, I would not say it is bad practice at all. It is just one solution to a problem that you will encounter every now and then.
In every case I have seen, I have made due with Dispatcher.CurrentDispatcher. For complex scenarios, this may not be sufficient, but I (personally) have not seen them.
Not entirely correct, but this line of thinking will not do any harm. Let me put it this way: the Dispatcher can be used to gain access to the UI thread for the application. But it is not in and of itself the UI thread.
BackgroundWorker is generally used when you have a time-consuming operation and want to maintain a responsive UI while running that operation in the background. Normally you do not use BackgroundWorker instead of Invoke, rather, you use BackgroundWorker in conjunction with Invoke. That is, if you need to update some UI object in your BackgroundWorker, you can Invoke onto the UI thread, perform the update, and then return to the original operation.
Yes. The UI thread of a WPF application, by definition, must be running in a single-threaded apartment.
There's a lot to be said about BackgroundWorker, I'm sure many questions are already devoted to it, so I won't go into too much depth. If you're curious, check out the MSDN page for BackgroundWorker class.
I have some code which executes a windows svc (another process) and updates the UI at the same time. The calls use BeginInvoke, like so:
Install.BeginInvoke((MethodInvoker) delegate { Install.Enabled = false; });
This is in the DoWork event handler. However, the UI still freezes up. Do I need a call to Application.DoEvents somewhere (if so, where?)? How can I eliminate the freezing?
In the button click, I have:
GetPrinterDto(DirectoriesTreeView.SelectedNode.Text);
InstallBackgoundWorker.RunWorkerAsync();
InstallBackgroundWorker just runs the code which updates the UI etc.
What I am trying to do is call a WCF server (hosted in a windows service - this is fine), but while that is off doing its thing, update the progress bar and a label with arbitrary values in an async fashion. When I select a treenode, the event handler for selected treenode is f ired, which may cause some of the slowdown. I will try putting this in its own backgroundworker.
While you certainly could place the call to update the UI (which is what your call to BeginInvoke is doing) in the DoWork method, you shouldn't, otherwise, you really wouldn't need the BackgroundWorker class.
Rather, you would call the ReportProgress method which would then fire the ProgressChanged event.
It's in the event handler of the ProgressChanged event that you would make the call to Install.Enabled = false.
The problem is not directly related to the use of BeginInvoke. It probably has more to do with how much it is being called. You could use ReportProgress in conjunction with the ProgressChanged event, but assuming you replace all of your BeginInvoke calls with ReportProgress then you may wind up with similar problems because BackgroundWorker will automatically marshal the event handlers on the UI thread using the same mechanisms that BeginInvoke/Invoke are using anyway. I would say the quick solution is to reduce the frequency at which you are attempting to update the UI.
Personally, I think the use of BeginInvoke to update the UI with worker thread progress is way overused. And in the same regard the BackgroundWorker class promotes this suboptimal method as well. It is usually better to have the worker thread publish update information periodically to a shared data structure and then the UI thread can pick it up on its own schedule (usually by polling using a Timer). This has several advantages:
It breaks the tight coupling between the UI and worker threads that the Control.Invoke\Control.BeginInvoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).
It is unfortunate that BackgroundWorker lacks the necessary mechanisms for using this alternate approach. However, you should be okay with using ReportProgress as long as you do not call it too frequently.
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.
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 )
I need to know whether Control.BeginInvoke and Control.Invoke calls will execute in the order they are called.
I have the following scenario:
UI thread is blocked
WCF thread calls Control.BeginInvoke
WCF thread calls Control.Invoke (or possibly BeginInvoke again)
UI thread is unblocked
??
The execution order of step 1-4 is guaranteed to be in the shown order (technically the order is not guaranteed to be that way, but the question I have is only relevant if the order is as shown).
The question I have is whether there is any chance that the Invoke/BeginInvoke call in step 3 is executed before the BeginInvoke call in step 2?
Also, please don't comment on blocking the UI thread.
In your case, step 2 will always execute before step 3. BeginInvoke on the UI thread will execute in the order it has been queued.
The UI thread is in fact a message pump, it has a single message queue with only one thread consuming it, so it's guaranteed that work items will be executed in the order they were queued.
It's with Delegate.BeginInvoke that the order of execution may be non-sequential.
BeginInvoke calls are queued on the destination thread (as they are posted in order of arrival).
Synchronous calls on the WCF Thread (step 3) may be executed before asynchronous calls (step 2) made from this thread.
Not enough information to give you a good answer. The UI thread is blocked so steps 2 and 3 must be running on a different thread. If there's no synchronization between the two, then how could we know any ordering?
Thread 1 Thread 2 Thread 3 Thread 4
Block UI Calls BeginInvoke
Unblock UI Calls Invoke or BeginInvoke BeginInvoke runs BeginInvoke runs
You've got a lot a parallelism going on, but from what you've described, there's no possible way we could tell you what possible orderings will occur, short of saying, "Anything." We can't even tell you that the calls to BeginInvoke won't happen before the UI thread is blocked or after the UI thread is unblocked.
No chance you can assume that but if there's actual some form of dependency between the two calls above have them waiting on a semaphore and only execute the dependent code when they're both completed.
If the reason why you're making the two calls at the same time is not performance then I would probably just execute the second call in the callback of the first (makes it a lot easier to debug).