I am new to WPF and have a question regarding dispatcher and Delegate.Invoke.
In a windows forms application, we can use the invoke method to make changes to UI controls from other threads. This works because invoke “executes the specified delegate on the thread that owns the control's underlying window handle” (as per msdn).
My question is:
Why doesn't Invoke work on WPF? It should be allowed to make changes to UI as the thread that owns the UI control gets to execute the delegate, but still it throws a runtime exception that “a thread is trying to modify an object that is owned by a different thread”.
How does the dispatcher manage to make changes to WPF controls while Invoke fails?
Is it possible to do cross thread programming in WPF without using dispatcher or background worker?
1) why doesn’t invoke work on wpf?
It works fine, but perhaps you're not using it correctly. I suggest you read the documentation
It should be allowed to make changes to UI as the thread that owns the UI control gets to execute the delegate, but still it throws a runtime exception that “a thread is trying to modify an object that is owned by a different thread”
Perhaps you created a UI object on a worker thread, then tried to add it to the main UI on the UI thread ? Without seeing your code, it's only a guess...
2)How does despatcher manage to make changes to wpf controls while invoke fails?
This question is not very clear, but it's probably related to the first question anyway...
3) Is it possible to do cross thread programming in wpf without using despatcher or background worker?
If you need to manipulate the UI from a worker thread, you have to use the dispatcher. BackgroundWorker also uses the dispatcher (indirectly, through the ISynchronizationContext interface) to raise events on the UI thread. There's no way around it.
Related
Simple question, though no one at the office seems to know and I can't find a good way to ask google this. In winforms, if you have a function that handles an event (in this case, on a focusLost), does that function happen on the same thread as the one that fired the event?
So if I have a textbox with focus, which is currently running on the UI thread, and I change focus, will the UI thread then run my function?
Yes, the UI thread will execute UI event handlers.
Generally, in Windows programming, you shouldn't be touching UI components on other threads. Windows Forms is designed to work via a single thread. If you need to heavy lifting that otherwise may freeze the UI thread, you spawn a new thread to do the work, then push the changes to the UI thread.
You can use SynchronizationContext.Current to post work to the UI thread. BackgroundWorker is handy for this as well.
I believe that is correct. Normally events are handled on the GUI thread. Here is a link below on how to do so in a different thread.
http://bytes.com/topic/c-sharp/answers/526484-handling-control-ui-events-worker-threads
I have an application which tab page based. To decrease the startup time I am creating only the tab page which is shown to the user.
After launching the Form, I used BackgroundWorker to create other tab pages. Tab pages contains usercontrols with databinding.
It is working fine. The issue is: With one tab page I am getting cross thread violation. That tab page having databinding also.
So what will be problem in this scenario?
Thanks is advance.
WinForms controls have thread affinity. The means they should be accessed on the same thead they are created on. This is because WinForms is actually just a wrapper around Win32 functionality and the code that manages your windows and child controls in Win32 is not thread safe. Hence your Form and child controls should only be accessed on the same thread they are created.
In your case you should not be creating TabPage instances using a BackgroundWorker thread or indeed any other thread than the main thread which is the location I assume you have the main Form that contains the TabControl you are adding the pages into.
Often developers get lucky and manage to use controls in different threads to which they were created and it does not crash. But this is just pure luck and sooner or later it will start failing.
I have two question regarding WPF Dispatcher Thread.
Does dispatcher thread keeps running when your WPF form is in minimized stat.
I have so many dynamic updated so I flow my updated till winform and then user Timer in winform to update UI. In winform when you minimized winform your Timer will stop working as it is created in UI thread. So my CPU utilization is low. If I have to achieve same behavior in WPF MVVM then how can I achieve that?
Both your questions seem to assume that minimizing your app will somehow stop some of your threads. I don't know where you got that idea, but it's completely wrong. Your UI thread is still running even when you're minimized. How else would it ever process the "restore" command when you un-minimize it? How would Windows be able to get its title to show on the taskbar?
You also seem to think that WPF has a "dispatcher thread" that's somehow special. That's not the case. The Dispatcher takes the place of the Windows message queue, which means it's attached to the UI thread. The thing you call a "dispatcher thread" is the same thing as the UI thread. If you're doing WinForms and WPF in the same app, they both run on the same UI thread (unless you're manually starting new threads and starting your own dispatchers on them, but that's a pretty unusual scenario).
And no, your Timer does not stop running just because your app is minimized (unless you manually wrote code to stop it). Try it: add a call to Console.Beep() in your timer tick event, and then try minimizing your app and see for yourself whether it keeps making noise.
Here's my guess: in your timer's Tick event, your WinForms app calls Invalidate(). When the app is minimized, Invalidate does nothing -- the window isn't shown, so there's nothing to invalidate -- so you see low CPU usage because it's not doing anything.
If you want the same behavior in WPF, your best bet is to add this code to the beginning of your Tick event:
if (WindowState == WindowState.Minimized)
return;
I've making a some application which build a huge-sized FlowDocument. The elapsed time of building FlowDocument was about 3~4 seconds.
So I like to building FlowDocument in BackgroundWorker, not UI thread. but BackgroundWorker can't return WPF UI object. (It occured InvalidOperationException exception.)
how can i solve this problem?
If you want to build a FlowDocument in another thread, it has to be a second UI-type thread, not a BackgroundWorker. In spite of what the documentation says, you CAN build more than one UI-type thread. However, you cannot create UI objects in one thread, and use them in another. You could save your FlowDocument to disk and then reload it in the foreground UI thread, though.
This article has a good example with two UI threads, and in fact I have used this code to process XPS files in a background thread, very similar to what you are doing. Make sure your second UI thread is set to STA apartment state, and as I said, do not try to use any UI objects created in one thread, in a different thread. It won't work.
I have been developing a Lync Silverlight application in Silverlight and now I am trying to shift it to WPF.
However, I am facing some thread affinity issues. For example I display the Lync client's state on my page in a textblock, and so in my code behind have wired a state changed event handler, that writes the new state into the textblock whenever the state of Lync client changes.
Now, this worked perfectly in silverlight but seemingly is not allowed in WPF.
Now my questions are:
How come it works in Silverlight bt not in WPF, even though Silverlight is supposed to be a subset of WPF?
Thread affinity is an important concept and I know we can use invoke dispatcher, but doesn't it just beat the concept of asynchronous programming in form of event handlers and callbacks?
I have a button defined in my XAML page, and the click event handler defined on it can access other UI elements, it does not suffer the problem outlined above.
But if I define a LyncClient instance in my code-behind, event handlers defined on it cannot access the UI elements. Why so, I detected no such difference between UIElements and other objects in Silverlight?
Based on above comments, I'll suggest the following "answer"...
I would guess it is more likely than not that there is some sort of different in the way that the SL API was written than that of the WPF api. That could explain the difference in the thread that is used when the API issues the callback. To verify this, you could:
Ask MS directly
Put some diagnostics code in your callback method to log the thread ID and compare that to the main thread of the application. Do this for both SL and WPF to see if they are the same or different threads.
Open the assemblies in Reflector to inspect how each API was written.
In terms of handling this specific situation, in your callback, you could:
Get the dispatcher object (different for SL than WPF) and always issue UI updates through Dispatcher.Invoke.
Use databinding and INotifyPropertyChanged to insulate the UI from the property. You could delcare a property on a ViewModel or in the code behind. Then bind the UI's textbox to that property. Databinding has some smarts in it that will automatically marshal property changes to the correct thread (in most cases anyway).
Hope that helps.