Best practice for controlling a busy GUI
Suppose a GUI (C#, WinForms) that performs work and is busy for several seconds. It will still have buttons that need to remain a开发者_StackOverflow中文版ccessible, labels that will change, progress bars, etc.
I'm using this approach currently to change the GUI when busy:
//Generic delegates
private delegate void SetControlValue<T>(T newValue);
//...
public void SetStatusLabelMessage(string message)
{
if (StatusLabel.InvokeRequired)
StatusLabel.BeginInvoke(new SetControlValue<string>(SetStatusLabelMessage, object[] { message });
else
StatusLabel.Text = message;
}
I've been using this like it's going out of style, yet I'm not quite certain this is proper. Creating the delegate (and reusing it) makes the whole thing cleaner (for me, at least), but I must know that I'm not creating a monster...
Another alternative is to use a BackgroundWorker and use ReportProgress when you need to update the GUI. This will handle the Invoke for you so that you don't have to worry about it.
Best practice here is to use a BackgroundWorker to run the long-running task. It's a special threading class set up specifically for WinForms, just for this purpose. You can send work to it, cancel it, and also let it send messages back to the WinForm thread to update status. Basically, by using a BackgroundWorker, your GUI stays free and active.
Others have mentioned using BackgroundWorker to run your work in. Is that what you are doing?
In any case, if you are you wondering what the best way to update the UI from your background thread is, what you are doing looks fine, although I recommend using Invoke
instead of BeginInvoke
. Also, instead of declaring your own separate delegate, you can use MethodInvoker
to simplify your code:
StatusLabel.Invoke(new MethodInvoker(delegate() { /* Update control here */ }));
It looks right to me. So long as you are encapsulating that sort of thing into its own well-tested class, there should be no problem with it.
精彩评论