Whenever I get a Invalid-CrossThread-Access error in my windows phone project, I execute my code inside Deployment.Current.Dispatcher.BeginInvoke(() => {}) and everything works fine after that. However I never clearly understood the meaning of it.
Can someone put some light on it giving detailed explanation on how does it resolves my cross thread errors and what each of its parts mean. As far as I have googled for it, it is used to execute some code on UI thread.
But what are deployment, current, and dispatcher objects. How else can I use them.
TIA
The problem lies in the design of the Windows platform. You can't change the user interface (specifically Win32 objects) from another thread then the objects are created from.
Dispatcher.BeginInvoke executes the delegate provided as parameter on the UI thread, not on the thread it is called from.
Deployment.Current is a singleton reference to the current running application, the Dispatcher is the part of the program that is responsible for passing messages around. BeginInvoke the method that does actually finds the right thread and executes the delegate.
The difference between BeginInvoke and Invoke it that the first is ran asynchronously. Invoke is executed immediately and execution is suspended until the method finishes.
Related
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.
How InvokeRequired and Invoke let us make our apps thread safe.
Let's consider such code:
private void ThreadSafeUpdate(string message)
{
if (this.textBoxSome.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(msg);
this.Invoke
(d, new object[] { message });
}
else
{
// It's on the same thread, no need for Invoke
this.textBoxSome.Text = message;
}
}
Is it possible to change state of InvokeRequired after InvokeRequired and before Invoke? If not, then why?
How does Invoking make it thread safe?
If InvokeRequired illustrate is current thread owning control, how would the thread know that it is or it is not the owner.
Let's consider that SomeMethod() is currently running on Thread1. We would like to call it from Thread2. Internally this method updates some field. Does Method.Invoke contain some kind of lock mechanism internally?
What if SomeMethod() takes very long time and we would like to run something other on the control owner thread. Does Invoking lock the owner thread or is it some kind of a background thread safe task?
ThreadSafeUpdate() //takes 5 minutes in Thread2
ThreadSafeUpdate() //after 2 minutes, we are running it in other thread2
ThreadSafeUpdate() //next run from Thread3
I think it is some kind of general pattern which can be implemented outside of winforms, what's its name?
Is it possible to change state of InvokeRequired
Yes, and it is a pretty common occurrence. Either because you started the thread too soon, before the form's Load event fired. Or because the user closed the window just as this code is running. In both cases this code fails with an exception. InvokeRequired fails when the thread races ahead of the window creation, the invoked code fails when the UI thread races ahead of the thread. The odds for an exception are low, too low to ever diagnose the bug when you test the code.
How Invoking make it thread safe?
You cannot make it safe with this code, it is a fundamental race. It must be made safe by interlocking the closing of the window with the thread execution. You must make sure that the thread stopped before allowing the window to close. The subject of this answer.
how would he know that he is or he is not owner.
This is something that can be discovered with a winapi call, GetWindowsThreadProcessId(). The Handle property is the fundamental oracle for that. Pretty decent test, but with the obvious flaw that it cannot work when the Handle is no longer valid. Using an oracle in general is unwise, you should always know when code runs on a worker thread. Such code is very fundamentally different from code that runs on the UI thread. It is slow code.
We would like to call it from Thread2
This is not in general possible. Marshaling a call from one thread to a specific other thread requires that other thread to co-operate. It must solve the producer-consumer problem. Take a look at the link, the fundamental solution to that problem is a dispatcher loop. You probably recognize it, that's how the UI thread of a program operates. Which must solve this problem, it gets notifications from arbitrary other threads and UI is never thread-safe. But worker threads in general don't try to solve this problem themselves, unless you write it explicitly, you need a thread-safe Queue and a loop that empties it.
What's if SomeMethod() takes very long time
Not sure I follow, the point of using threads is to let code that takes a long time not do anything to harm the responsiveness of the user interface.
I think it is some kind of general pattern
There is, it doesn't look like this. This kind of code tends to be written when you have an oh-shoot moment and discover that your UI is freezing. Bolting threading on top of code that was never designed to support threading is forever a bad idea. You'll overlook too many nasty little details. Very important to minimize the number of times the worker thread interacts with the UI thread, your code is doing the opposite. Fall in the pit of success with the BackgroundWorker class, its RunWorkerCompleted event gives a good synchronized way to update UI with the result of the background operation. And if you like Tasks then the TaskScheduler.FromCurrentSynchronizationContext() method helps you localize the interactions.
Usually, no. But it could happen if you're using await between the InvokeRequired check and Invoke call without capturing the execution context. Of course, if you're already using await, you're probably not going to be using Invoke and InvokeRequired.
EDIT: I just noticed that InvokeRequired will return false when the control handle hasn't been created yet. It shouldn't make much of a difference, because your call will fail anyway when the control hasn't quite been created yet, but it is something to keep in mind.
It doesn't make it thread-safe. It just adds the request to the control's queue, so that it's executed the next available time on the same thread the control was created on. This has more to do with windows architecture than with general thread-safety. The end result, however, is that the code runs on a single thread - of course, this still means you need to handle shared state synchronization manually, if any.
Well, it's complicated. But in the end, it boils down to comparing the thread ID of the thread that created the control, and the current thread ID. Internally, this calls the native method GetWindowThreadProcessId - the operating system keeps track of the controls (and more importantly, their message loops).
Invoke cannot return until the GUI thread returns to its message loop. Invoke itself only posts the command to the queue and waits for it to be processed. But the command is run on the GUI thread, not the Invoke-caller. So the SomeMethod calls in your example will be serialized, and the Invoke call itself will wait until the second call finishes.
This should already be answered. The key point is "only run GUI code on the GUI thread". That's how you get reliable and responsive GUI at all times.
You can use it anywhere you've got a loop or a wait on some queue. It probably isn't all that useful, although I have actually used it already a few times (mostly in legacy code).
However, all of this is just a simple explanation of the workings. The truth is, you shouldn't really need InvokeRequired... well, ever. It's an artifact of a different age. This is really mostly about juggling threads with little order, which isn't exactly a good practice. The uses I've seen are either lazy coding, or hotfixes for legacy code - using this in new code is silly. The argument for using InvokeRequired is usually like "it allows us to handle this business logic safely whether it runs in the GUI thread or not". Hopefully, you can see the problem with that logic :)
Also, it's not free thread-safety. It does introduce delays (especially when the GUI thread is also doing some work that isn't GUI - very likely in code that uses InvokeRequired in the first place). It does not protect you from accesses to the shared state from other threads. It can introduce deadlocks. And don't even get me started on doing anything with code that uses Application.DoEvents.
And of course, it's even less useful once you take await into consideration - writing asynchronous code is vastly easier, and it allows you to make sure the GUI code always runs in the GUI context, and the rest can run wherever you want (if it uses a thread at all).
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.
We're creating a few threads in a Windows.Forms solution.
We've also got a BrowserControl (yup, it's OAUTH) and of course I'm finding issues with debugging -
Cross-thread operation not valid: Control 'xxForm' accessed from a
thread other than the thread it was created on
And yet I am calling 'correctly'
xxForm.Show()
by ensuring it's wrapped in an invoke call
.Invoke(new MethodInvoker())
and still I get the thread issue. I can do everything else (Focus, BringToFront) it's the Show that errors.
Moreover, the GUI never gets the browser response and shows. In the VS debugger I get the above threading erropr (apartment state of background thread == MTA). When run as an EXE the same code has a threading aparement of STA and the GUI will never show when debugging, but if I run the EXE directly, there's no threading issue, the browser control just never responds to input.
Spo the questions are:
Why the different behjaviour in VS / EXE?
How do I debug in VS?
Does the BrowserControl play ok with multiple threads?
Update
YES I KNOW there's no code - it's too long. I'll see what I can do.
Also please read the question before posting an answer. I am invoking the background thread on the UI thread. That's not the issue. This has NO EFFECT on the result. I'll down vote answers that recommend that.
Also some hope - I've searched for many hours. It's linked the the message pump. Unless the message pump is running the DocumentCompleted event isn't received.
Update 2
Best I manage is pseudo code:
Program:
startWorkQueue
LoadForm (don't show)
Thread1:
addToQueue
Thread2:
readFromQueue
ShowForm (on occasion)
Now the ShowForm method is on a Windows.Form control.
Within this any call is made via an Invoke, so that despite the 2nd thread making the call the ShowForm, the actual .Show() etc etc calls are on the UI thread.
So what am I missing? I just don't understand why there's a cross thread exception....
Ok I've found out what was going on and I'll post here for reference.
I hope it helps someone in the future.
We had some different constraint to the vanilla Forms applications - our Forms were created on the Main thread but had Show() called on a different thread. We also don't have a starting UI - we sit in the background and sometimes react to events with UI prompts.
As such a number of issues hit us. Rather than list them all I'll detail our takeaways:
Application.Run
If decide NOT to Show a Form at the start of your application… then you'll need to consider threads carefully (see Form.Show notes)
Form.Show
This does all resource allocation etc, NOT the Load/ctor
Performs handle creation / resource allocation
Handle creation
Hwnd
If we attempt to access certain Form properties before it has Show(n) then you'll need to create a handle manually (or an Exception is created)
• As easy as if (!IsHandleCreated) { CreateHandle(); }
HOWEVER
This create the control/form
Therefore the control/form is created on the Thread that calls the Handle create
This must be the same UI thread (STA) as the Main function
• Otherwise much weirdness occurs
SO
You aren't restricted by what to do with Application.Run
You can access properties in .Show (but you may need to create a handle first)
You can call Show from a different thread, but ensure the handle is ONLY created on the main thread
I hope it helps, I can provide more details on our specific problems if need be.
Various aids that helped included displaying ManagedThread AND ProcessId in the log and scouring MSDN.
Since the code has not been pasted, I would like to remind you that in WinForms, the UI elements should be accessed only on the UI thread. Any other thread apart from UI thread should not be updating the UI elements directly.
I've got a bit of an issue here where I want to modify GUI elements from various worker threads. Until today, the method I was using worked, but it was most likely very incorrect.
The simplest case involves my plugin's GUI, which does something in a worker thread, and when that method completes its work, it calls my callback. That callback method is handled from the same thread, so it cannot do any GUI work. However, when my plugin's GUI is displayed by my main app GUI, my plugin GUI caches its Dispatcher reference -- when I do need to do GUI updates (or in this case, display a dialog), I call Dispatcher.Invoke(...).
Is there any inherent danger in setting the Dispatcher in my plugins like this?
Today, I have a new problem with this approach. My application needs to call that method in my plugin that launches the worker thread and displays a dialog. If I call the method before I open the plugin's GUI (which caches the Dispatcher reference), the operation will fail because the Dispatcher is null. I always check for that to make sure the app doesn't crash. However, now that the dialog isn't displayed, the necessary user interactions cannot proceed.
Can anyone suggest a better method for using the Dispatcher to ensure that I can display / modify a plugin's GUI elements from my main application? The only thing I can think of right now is to have my main application pass its Dispatcher reference to my plugin loader, add a "SetDispatcher" method to my plugin interface, and then have the plugin loader call this for every plugin that needs to be loaded.
If your plugin's GUI must exist by the time the background thread finishes, you should probably make sure that the plugin GUI creation/instantiation happens before you spin off that background process. That way, the plugin GUI element(s) Dispatcher is set by the framework before your async stuff finishes.
At a higher level (you may or may not be able to address this), it seems like you've got some inappropriate coupling between the GUI and the stuff that's occurring in the background.
For now, I've found that a nice solution, appropriate or not, is to export the main thread's Dispatcher via MEF, and then allow all of the plugins to import it. It seems like the cleanest way to deal with this sort of thing right now.