-- winform .net core中跨线程修改UI界面与Task,MethodInvoker的应用
【官网】:无
应用场景
多个线程竞争读写同一个资源往往会造成意外结果甚至异常,winform(包括winform .net core)UI界面也是一种资源,所以跨线程修改UI界面经常会抛异常。该问题下我们可以采用Task + MethodInvoker的方式完成跨线程对UI对的修改。基础资源
.net core 3.1或.net framework 4.5及以上
使用须知
使用Task.Wait时,建议都加上ConfigureAwait(false)防止卡死,当然更好的办法是把相关的方法变成异步的。
配置步骤
无
常见问题
快速入门
A)示例1-后台线程或Task修改界面操作.
/// <summary> /// 功能简介:封装一个对UI界面的操作(支持跨线程调用) /// 作者: http://config.net.cn /// 创建时间:2022-1-8 /// </summary> /// <param name="action"></param> private void OnResponseForUI(string action) { MethodInvoker method = delegate { if (action == "DownLoad") btnSendEmail.Enabled = false; else if (action == "Finish_DownLoad") btnSendEmail.Enabled = true; }; BeginInvoke(method); } /// 功能简介:一个基于后台异步任务的操作,操作过程可以修改UI界面 /// 作者: http://config.net.cn /// 创建时间:2022-1-8 private void btnStartDownLoad_Click(object sender, EventArgs e) { OnResponseForUI("DownLoad"); Task task = new Task(async delegate { try { await Download();//耗时的或者会阻塞的操作(可以放到子线程,也可以放到Task中 } catch (Exception ex) { TipsCrossThread(ex.Message + "," + ex.StackTrace); } OnResponseForUI("Finish_DownLoad"); }); task.Start(); }
A2)示例2-创建一个TaskEngine,并实现开启,停止等。
public class MetaTaskEngine { private Task _task; private CancellationTokenSource _cancellationTokenSource; private MetaTaskEngine() {
//todo:实现任务处理的初始化 }
private void WorkProcess(){
//todo:处理任务的实际工作
} public void Stop() { if (_cancellationTokenSource != null) { _cancellationTokenSource.Cancel(); } }
public void Start(MetaTask task) { if (_cancellationTokenSource != null) { _cancellationTokenSource.Cancel(); } if (_task != null) { try { _task.Dispose(); } catch (Exception ex) { //todo: exception process } } _cancellationTokenSource = new CancellationTokenSource(); _task = new Task(delegate {WorkProcess();}, _cancellationTokenSource.Token); _task.Start();
//注:还可以使用下列语句来判断Task的执行状态
if (_task.IsCompletedSuccessfully)//任务成功 {
Console.WriteLine("_task.IsCompletedSuccessfully"); } if (_task.IsCompleted)//任务完成 {
Console.WriteLine("_task.IsCompleted");
}
}
}