我正在尝试在登录时启用忙碌指示器。我遇到的问题是在完成所有操作后才会启用它。一旦我登录以尽快启动指标,我怎样才能立即告诉线程更新UI?
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..
}
答案 0 :(得分:8)
UI线程空闲后,UI将立即更新。在这种情况下,不需要Dispatcher.Invoke
,因为您已经在UI线程中。
这里的关键是将“工作”移动到后台线程中,即:
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());
}
如果您使用的是C#5,则可以通过使登录和其他代码异步来简化此操作:
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;
}
答案 1 :(得分:0)
您可以使用BAckground Worker Thread并将其两个eventHandler添加到您想要处理的事件中。 例如 -
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();
这样它也不会导致任何线程错误..
启用BusyIndicator作为TimeTaking TAsk启动和timeTaking任务完成时只需在RUnWorkerCompleted事件中禁用忙碌指示器。