案例:提交登錄,后台(C#)長時間處理邏輯業務,導致前端界面阻塞(停止動畫,頁面不可以移動等)

解決方案,使用 BackgroundWorker:
說明:BackgroundWorker類允許您在單獨的線程上執行某個可能導致用戶界面(UI)停止響應的耗時操作(比如文件下載數據庫事務等),並且想要一個響應式的UI來反應當前耗時操作的進度。
MVVM模式,登錄示例:
public class WindowLoginViewModel
{
//定義BackgroundWorker
BackgroundWorker backgroundWorker;
//ViewModel構造函數
public WindowLoginViewModel()
{
//BackgroundWorker實例化
backgroundWorker = new BackgroundWorker();
//指示BackgroundWorker是否可以報告進度更新
//當該屬性值為True是,將可以成功調用ReportProgress方法,否則將引發InvalidOperationException異常。
backgroundWorker.WorkerReportsProgress = true;
//指示BackgroundWorker是否支持異步取消操作
//當該屬性值為True是,將可以成功調用CancelAsync方法,否則將引發InvalidOperationException異常。
backgroundWorker.WorkerSupportsCancellation = true;
//用於承載異步操作
backgroundWorker.DoWork += backgroundWorker_DoWork;
//報告操作進度
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
//異步操作完成或取消時執行的操作,當調用DoWork事件執行完成時觸發
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
}
//登錄命令
public DelegateCommand<Window> LoginCommand
{
get
{
return new DelegateCommand<Window>(Login);
}
}
//登錄業務
public void Login(Window window)
{
//指示BackgroundWorker是否正在執行一個異步操作
//此屬性通常放在BackgroundWorker.RunWorkerAsync()方法之前,避免多次調用RunWorkerAsync()方法引發異常
if (backgroundWorker.IsBusy)
{
return;
}
//開始執行一個后台操作。
//調用該方法后,將觸發BackgroundWorker.DoWork事件,並以異步的方式執行DoWork事件中的代碼
//RunWorkerAsync(Object)方法允許傳遞一個Object類型的參數到后台操作中,並且可以通過DoWork事件的DoWorkEventArgs.Argument屬性將該參數提取出來
backgroundWorker.RunWorkerAsync(window);
}
//取消命令
public DelegateCommand<Window> CancelCommand
{
get
{
return new DelegateCommand<Window>(Cancel);
}
}
//取消業務
public void Cancel(Window window)
{
//請求取消當前正在執行的異步操作
backgroundWorker.CancelAsync();
}
//BackgroundWorker報告操作進度
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs args)
{
//狀態說明
//object userState = args.UserState;
//狀態參數
//progressBar.Value = args.ProgressPercentage;
}
//BackgroundWorker執行業務
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs args)
{
//指示應用程序是否已請求取消后台操作
if (backgroundWorker.CancellationPending)
{
args.Cancel = true;
return;
}
else
{
Window window = (Window)args.Argument;
//ReportProgress(Int, Object)方法允許傳遞一個Object類型的狀態對象到 ProgressChanged事件中,並且可以通過ProgressChanged事件的ProgressChangedEventArgs.UserState屬性取得參數值。
backgroundWorker.ReportProgress(0, "參數說明");
Models.Users user = new Models.Users();
Application.Current.Dispatcher.Invoke((Action)(() =>{
Globle.mainWindow = new MainWindow();
window.Close();
}));
}
}
///BackgroundWorker執行完成
//此處UI會阻塞,所以不要放過多的處理程序
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs args)
{
if (args.Error != null)
{
MessageBox.Show(args.Error.ToString());
return;
}
//線程取消
if (args.Cancelled)
{
}
if (!args.Cancelled)
{
Application.Current.Dispatcher.Invoke((Action)(() =>{
Globle.mainWindow.Show();
}));
}
}
}
DoWork示例:
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (!bw.CancellationPending)
{
//Do SomeThing
//在合適的時候使用
//backgroundWorker.ReportProgress(i);
//報告一下進度
}
}
簡單示例:
Action workAction = delegate {
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (o, ea) =>
{
Login(Name, Password);
};
worker.RunWorkerCompleted += (s, e) =>
{
if (e.Error != null)
{
loginStatus.Text = "登錄失敗!";
}
else
{
loginStatus.Text = "登錄成功!";
}
};
worker.RunWorkerAsync();
};
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, workAction);
