Reputation: 4122
I'm trying to enable a busy indicator on log in. The problem I'm having is it won't enable until everything is done executing. How can I immediately tell the thread to update the UI as soon as I log in to start the indicator asap?
private void LoginButton_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.Invoke((Action)(() =>
{
radBusyIndicator.IsBusy = true;
//var backgroundWorker = new System.ComponentModel.BackgroundWorker();
//backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(backgroundWorker_DoWork);
//backgroundWorker.RunWorkerAsync();
}));
string error = string.Empty;
long userId = 0;
//Login code here....
//........... bunch of other code. etc..
}
Upvotes: 2
Views: 769
Reputation: 624
You can use BAckground Worker Thread and subsribe its two eventHandlers to your events which you want to work on.. for eg-
BackgroundWorker Worker=new BackgroundWorker();
worker.DoWork+=Yorevent which will do the timeTaking Task();
Worker.RunWorkerCompleted+=YOurEvent which will Update your UI after the work is done();
worker.RunWorkerAsync();
this way it will not cause any thread Error too..
Just Enable your BusyIndicator as Your TimeTaking TAsk start and when the timeTaking Task is done just Disable your Busy Indicator in RUnWorkerCompleted Event.
Upvotes: 0
Reputation: 564821
The UI will update as soon as the UI thread is free. There is no need for Dispatcher.Invoke
in this case, as you're already in the UI thread.
The key here is to move the "work" into a background thread, ie:
private void LoginButton_Click(object sender, RoutedEventArgs e)
{
radBusyIndicator.IsBusy = true;
LoginButton.IsEnabled = false; // Prevent clicking twice
string error = string.Empty;
long userId = 0;
// Start this in the background
var task = Task.Factory.StartNew(()=>
{
//Login code here....
//........... bunch of other code. etc..
});
// Run, on the UI thread, cleanup code afterwards
task.ContinueWith(t =>
{
// TODO: Handle exceptions by checking t.Exception or similar...
radBusyIndicator.IsBusy = false;
LoginButton.IsEnabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
If you're using C# 5, you can simplify this by making your login and other code asynchronous:
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
radBusyIndicator.IsBusy = true;
LoginButton.IsEnabled = false; // Prevent clicking twice
long userId = 0;
// Call async method with await, etc...
string error = await DoLoginAsync(userId);
var result = await BunchOfOtherCodeAsync();
radBusyIndicator.IsBusy = false;
LoginButton.IsEnabled = true;
}
Upvotes: 9