案例:提交登录,后台(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);
