一、背景
最近用.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