Background
I faced this problem a couple of years ago and got this very helpful answer from Stephen Cleary. Problem with VSTO add-ins is that they do not set a SynchronizationContext and therefore async calls do not resume on UI thread, causing all sorts of cross-thread access troubles. The solution, as he mentioned is to manually call SetSynchronizationContext before calling any async function.
I have been using this technique since then and thought that was all there was to it. But today I have seen a situation where even manually setting the context does not force it to resume on calling thread.
Situation
My VSTO add-in contains a WPF pane (inside a CustomTaskPane) which is bound to its ViewModel that contains several AsyncRelayCommand properties (from WCT). One of these commands calls my Data Service which in turn calls a RestSharp methods to fetch data from the API server.
All these calls use async/await and all these call use ConfigureAwait(false) except the one at the top level (i.e. the command itself). Here is a snapshot of how this call-site looks like:
As you can see, I have manually called SetSynchronizationContext before doing the await call. It also shows that SynchronizationContext.Current is set after it resumes after the await call, but somehow the code is still running on the worker thread. I also verified that the code was running on UI thread when it hit line 259 before drilling down into the await call.
I have already spent a lot of time and effort on this and can't make any sense of it. Can anyone help me figure out if I'm missing something obvious?
You need to use an instance of the WindowsFormsSynchronizationContext class instead.
The WindowsFormsSynchronizationContext class provides a synchronization mechanism for Windows Forms.
The DispatcherSynchronizationContext class is for WPF applications which uses two threads. One thread is background thread for rendering and the other thread is for UI. So, UI elements in one thread are not accessible to other UI threads. Microsoft introduced the dispatcher which is responsible for multiple UI threads interaction.
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 a large WPF MVVM application (over 100 windows currently and growing.) Although I try to do everything I can on background threads there always comes a time the results must be sent back to the UI thread to be displayed. When you have many windows doing this at the same time it can effect performance.
I've tried to run each window on a separate UI thread in the past but ran into so many threading issues I had to revert back to WPF's default model of only 1 UI thread per app.
I know with windows 10 coming many users will open even more windows on separate desktops and thus make this worse.
Anyone know how to get multiple UI threads to work correctly in WPF? Or have any info I can investigate to help get my app further down this road?
I approach I tried in the past was to do something similar to this:
private void OnCreateNewWindow(
object sender,
RoutedEventArgs e)
{
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
This was about 2 years ago and I can no longer recall all the issues I faced using this unfortunately.
Is there another way? Has anyone gotten an app with many windows to work correctly using this approach or another?
In general, it "works". The main thing you have to do is set the thread to STA (as in your example). But you gain little or nothing by running some of the UI in a different thread. Each thread can still be blocked by long-running tasks, so you still need to execute those in yet another thread, and you still have the cross-thread issue requiring some kind of marshaling back to the UI thread (e.g. Dispatcher.Invoke()).
Furthermore, with more than one UI thread, now not only do you have to keep track of which UI thread goes with which UI object (since they still can be used only with the thread that owns them), you will have more problems with UI objects interacting with each other, because those owned by different threads are mutually exclusive. Each is required to be accessed only in the thread in which it's owned, so the only way to have them work together is to create some kind of proxy system to pass data and events back and forth between threads.
Basically, it never was and still is not a good idea to create more than one thread for the UI.
Fortunately, as of .NET 4.5 and C# 5.0, there are framework and language features that greatly simplify the handling of background operations and the marshaling of information back to the UI thread. With the async/await feature, you can initiate asynchronous operations with framework features like the Task<T> class or certain class methods (usually with names ending in the word Async), have the UI thread unblocked for the duration of the operation, and yet easily write code to handle whatever work has to be done at the end of the operation.
There is also the Progress<T> class, which implements the IProgress<T> interface in a way that is convenient for dealing with UI progress updates, i.e. invokes the callback on the UI thread (as long as you create the Progress<T> instance in the UI thread, of course).
So, take the path that .NET and C# are encouraging you to take, and avoid the one that is hard. Keep all your UI in a single thread, and solve whatever issues come up using the tools provided instead of trying to fight the API. :)
Does anyone know why this code is slowing down the UI:
Thread trdGenerateTrajectory = new Thread(() => HeavyMethod());
trdGenerateTrajectory.Start();
trdGenerateTrajectory.Join();
This is supposed to be in a separate thread than the main thread, am I right? If so, why running it slows down/freezes the UL?
EDIT: Thanks for your comments. I removed Join(), but it still freezes the UI. Any idea?
UPDATE: The HeavyMethod() method is calling a method from a Matlab dll that I created. The method in the dll generates manipulation trajectory for a robot. My project is a heavy robotics project that communicates with lots of hardware/devices. The project has 12 backgroundworkers and one timer. The timer is responsible for updating the UI and all of the texts/colors/images/... on it. I haven't had any issue so far with the backgroundworkers and the timer and no matter how heavy were the tasks they are runing, I never saw any delay or stop on the timer and UI update. However, when I call this specific method in Matlab dll, I see a full stop on UI being updated until the method is completed. This is what I experienced:
I used threads (above code) with no luck.
I then moved the method and the process after running method into another backgroundworker, again with no luck.
Then I realized that just some of the textboxes on my form are experiencing this issue. They are those that are getting their values from another method of the same Matlab dll. That was the time that I realized that this issue has nothing to do with threads/backgroundworkers and is related to the Matlab way of running methods. Maybe it is single threaded!? Anyway, I though it may help if I make separate dll for this specific method that generates trajectory, so I created another dll, but I experienced the exact same issue. It seems like Matlab dll can only run one method at a time no matter if you call them from different threads or even from separate dll. I believe I should ask this in separate SO question and I will, but, in the meantime, do you have any comment on this? (Update: I didn't receive any reply so I posted a new question: Calling two functions from a single Matlab dll at the same time)
Although you're running your computation on a background thread, your Join call causes your UI thread to block anyway until your computation completes.
The proper way to do this today would be using the async and await keywords. If you really want to restrict yourself to threads, you can use an Invoke call within the thread to dispatch control back to the UI thread once the computation completes:
Thread trdGenerateTrajectory = new Thread(() =>
{
HeavyMethod();
this.Invoke(new Action(() =>
{
// Update UI here.
}));
});
trdGenerateTrajectory.Start();
// trdGenerateTrajectory.Join(); <- do not block
Edit: Assuming that you want to run your computation in response to some button click (or any other event), you can use the async pattern in the event handler like so:
private async void myButton_Click()
{
await Task.Run(HeavyMethod);
// Update UI here.
}
You're starting the thread and immediately joining it. Joining the thread means that you are waiting for it to end.
Normally, user interfaces are single threaded. This means that your method needs to return for another event to be processed.
I am a beginner with WPF, in my application I need to perform a series of Initialization steps, these take 10-15 seconds to complete during which my UI becomes unresponsive.
I was using yesterday the background worker but it didn't update my window, in fact it was frozen. Not sure, but maybe it didn't work because this control is only for Windows Forms.
UPDATE:
If not too much trouble, can you post me an example to use the alternative? For my case, the program will get some values from a database in a blucle.
Dispatcher.
The Dispatcher maintains a prioritized queue of work items for a specific thread. This might help you for updating your UI. If you have a lot of UI related initializations even this won't be able to help you much.
Dispatcher is not always an alternative to BackgroundWorker actually. The best practice is to select the more appropriate one as per your requirement. For example if you want something to execute without queuing BackgroundWorker is the solution. On the other hand if queuing is not a problem then Dispatcher is an alternative. For example, Dispatcher is using in Spell checkers and syntax highlighting functionality.
WPF Thread Model
All WPF applications start out with two important threads, one for
rendering and one for managing the user interface. The rendering
thread is a hidden thread that runs in the background, so the only
thread that you ordinarily deal with is the UI thread. WPF requires
that most of its objects be tied to the UI thread. This is known as
thread affinity, meaning you can only use a WPF object on the thread
on which it was created. Using it on other threads will cause a
runtime exception to be thrown. Note that the WPF threading model
interoperates well with Win32®-based APIs. This means that WPF can
host or be hosted by any HWND-based API (Windows Forms, Visual Basic®,
MFC, or even Win32).
The thread affinity is handled by the Dispatcher
class, a prioritized message loop for WPF applications. Typically your
WPF projects have a single Dispatcher object (and therefore a single
UI thread) that all user interface work is channeled through.
NOTE :
The main difference between the Dispatcher and other threading methods
is that the Dispatcher is not actually multi-threaded. The Dispatcher
governs the controls, which need a single thread to function properly;
the BeginInvoke method of the Dispatcher queues events for later
execution (depending on priority etc.), but still on the same thread.
See this thread for more information.
You could also queue items up with the thread pool and run the tasks like that, but be careful, if your tasks need to update the UI when they are finished you will have to marshal the data back to the UI thread.
One could use asynchronous delegates.
http://msdn.microsoft.com/en-us/library/ms228963.aspx
Just make sure if you are doing any UI related updates use:
Dispatcher.CheckAccess()
Here a simple example:
private void HandleUIButtons()
{
if (!btnSplit.Dispatcher.CheckAccess())
{
//if here - we are on a different non-UI thread
btnSplit.Dispatcher.BeginInvoke(new Action(HandleUIButtons));
}
else
{
btnSplit.IsEnabled = true; //this is ultimately run on the UI-thread
}
}
Taken from here:
http://blog.clauskonrad.net/2009/03/wpf-invokerequired-dispatchercheckacces.html
Sometimes I saw that when I call a method from my form to do something that my UI freezes. How to solve this problem? If I call that method in separate thread then problem will be solved?
If I call method in separate thread like the code below
new System.Threading.Thread(delegate()
{
HeavyMethod();
}).Start();
does this solve my problem or is there any better solution?
Call the method on a Background Worker would be the best solution.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Doing that you can control when things get updated (using the Report Progress Feature) and allow you to cancel the work.
Also, make sure that whatever resources you manipulate in the backgroundWorker1.RunWorkerAsync(); are properly shared. You can get into what is called "Race Conditions" which causes your output to be non-determanistic (e.g. you won't get the same results every time you run the method)
For a good walk through on Multithreading and shared resources, see this link:
http://www.c-sharpcorner.com/uploadfile/mgold/multithreadingintro10062005000439am/multithreadingintro.aspx?articleid=920ecafc-e83b-4a9c-a64d-0b39ad885705
If you are calling your method in response to an event, then by default the method will be running on the GUI thread (the thread that the runtime uses to handle all user events). If that method is huge and/or heavy, then it will "freeze" the UI as you describe.
Making it run on a separate thread is a viable solution for many of these cases.
There are cases, however, when you'll actually want the UI to "block" (for example, if you are updating a lot of controls, you don't want the user to mess with them in the meanwhile). For such cases, the sanest approach is to pop up a modal "wait" dialog.
Since it is C# 2.0, I suppose it is WinForms. Don't hold up the UI thread with CPU-bound code.
You can spawn a new thread to run your CPU-bound code, but you have to be careful not to access WinForms controls, especially not to update control properties. Many WinForms controls can only be accessed/updated from the UI thread. Check the InvokeRequired field to see if you need to marshal (i.e. use Invoke) the call from another thread back to the UI thread.
Also consider using the ThreadPool instead of creating a new thread.
That is correct, If you move the heavy processing off of the UI Thread then it should free up the UI to redraw. For what you want to do your implementation should work just fine. Although ThreadPooling or BackgroundWorker would be the suggested implementations (http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v=VS.80).aspx), (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx).