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).
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 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
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.
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.
Is there a way to invoke a method on a background thread ?
I am aware of BackgroundWorker/Creating a thread or use ThreadPool.QueueUserWorkItem etc but that's not the answer i am looking for
for e.g. the SCSF has attributes to ensure the method is invoked on a background or a UI thread
I'd like to do something similar for a small app and am looking for a working example
I think the BackgroundWorker will fit your needs. It allows you to run an operation in the background in a Winform app. Those articles have working examples. :)
There are many ways to invoke a method on a background thread.
Do you want to block while the method is running? Do you want a result returned from the method? Do you want this result displayed in the UI? Is the method called only once? Many times, as needed? Many times in a loop? Asynchronously? Should the background thread continue if your app quits? The answer to these questions will tell you which method you should use.
You can get an overview of the various thread message passing methods from a great article at The Code Project.
Thread pool already uses background threads. However, you don't have any control over those threads. If you want control, then you need to use System.Threading.Thread. This gives you more control over how a thread is created (background, foreground, etc) and managed (suspend, resume, sleep, etc).