一、背景
最近用.Net WinForm做一个桌面应用程序,刚开始有一些问题,后面总结出做WinForm最常见的两个问题,就是多线程的使用和多线程中的控件操作。
其实挺简单,但是没做过的话也会耽误一点时间。
二、技术
1、使用多线程
为什么要开多线程?因为不开多线程,界面会出现卡死的情况,体验很不好。
先看一下线程要做的事情(for循环内部代码):
Action action = () => { while (true) { try { var stop = false; lock (lockObj_stop) { stop = IsStop; } if (stop) { OperationLog.AddLog(new OperationLogModel() { CreateTime = DateTime.Now, Remark = $"线程:{Thread.CurrentThread.ManagedThreadId},用户主动停止!线程任务结束!" }); break;//用户主动停止,本线程结束 } var otherSuccess = false; lock (lockObj_success) { otherSuccess = IsSuccess;//AddLog里有lock操作,lock嵌套容易死锁,所以找个临时中间变量 } if (otherSuccess) { OperationLog.AddLog(new OperationLogModel() { CreateTime = DateTime.Now, Remark = $"线程:{Thread.CurrentThread.ManagedThreadId},其他线程预约成功!线程任务结束!" }); break;//其他线程成功预约到,本线程结束 } var ret = requestOne(model);//请求网络,model是具体数据,for循环列表创建线程,每次model数据不同 if (ret) { lock (lockObj_success) { IsSuccess = true; } OperationLog.AddLog(new OperationLogModel() { CreateTime = DateTime.Now, Remark = $"线程:{Thread.CurrentThread.ManagedThreadId},预约成功!线程任务结束!" }); break;//结束 } } catch (Exception ex) { Log4netHelper.Error("出错!", ex); } } }
怎么开多线程?
方式1:线程池线程
(线程池把线程加入队列,不一定会立即执行,可能要排队)
var task = System.Threading.Tasks.Task.Factory.StartNew(action);
方式2:直接开新线程
(立即执行):
var thread = CommonFun.StartNewThread(action);
CommonFun.StartNewThread方法:
/// <summary> /// 开启新线程并返回线程对象 /// </summary> /// <param name="action"></param> /// <returns></returns> public static Thread StartNewThread(Action action) { Thread thread = new Thread(delegate () { action(); }); thread.IsBackground = true; thread.Start(); &nb