Reputation: 13990
I'm writting a Windows Forms application in C# that performs a lot of long-running procedures. I need to program the application so that the GUI doesn't lock. What is the best way to program it?
I know how to use the following:
BeginInvoke
/EndInvoke
Application.DoEvents()
repeatedly (probably not a good idea)BackgroundWorker
But how to manage GUI state with call backs, etc... is not trivial. Are there solutions for this (in the form of patterns or libraries)?
Upvotes: 0
Views: 1896
Reputation: 96702
Using BackgroundWorker
is the simplest way to do what you're trying to do. BackgroundWorker
simplifies the logic of dealing with threads, leaving you with very little code you have to write. You just have to handle three events (DoWork
, ProgressChanged
, and RunWorkerCompleted
) and follow a few principles:
ReportProgress
instead and handle the ProgressChanged
event in the UI logic.Error
property of the RunWorkerCompletedEventArgs
when the method is done and handle (or throw) the exception. If you don't do this, you won't know that your method failed.CancellationPending
property to see if cancellation has been requested. If it has, once it's done handling the cancellation, set the Cancel
property on the DoWorkEventArgs
object. Be aware that it's possible for CancellationPending
to be true and Cancel
to be false; this happens, for instance, when the user requests cancellation and the method finishes before it has a chance to check CancellationPending
.Cancel
in your RunWorkerCompleted
event handler, so that your UI can provide the proper response to what happened while the worker was running.The examples in the documentation all show the DoWork
event handler calling a method of the form. This is almost certainly not what you want to do. Separating business logic from UI is a good idea in general; in background tasks it's essential. If your long-running method is a member of a class that doesn't know that the UI even exists, there's no danger that you'll inadvertently have it call a method that updates a status bar or something.
Upvotes: 2
Reputation: 153
All your options are syntactic sugar of doing same thing (Asynchronous execution). May be with different levels of controls. I would go with BackgroundWorker, because your GUI (handled by the main thread) will always be responsive.
Upvotes: 0
Reputation: 3166
It is relatively simple to use the ThreadPool to fire off long running processes from the UI. If you want feedback you can use some event handlers to fire on certain events from the long running process, then register for them and update the UI as needed.
MVC is good, but you still need to make sure your process is firing off on a thread other than the UI thread.
Upvotes: 0
Reputation: 150108
The Model-View-Controller pattern separates the state of your UI from the visual aspects of the UI. As long as your MVC implementation is thread aware, it should solve the state management issue for you.
This is how I handle multi-threaded UI implementations.
EDIT: Here's a good post on selecting an MVC implementation for WinForms projects.
Upvotes: 1