经常做WinForm开发的人可能会遇到这样一种情况,WinForm程序后台有许多线程在执行任务,前台界面需要适时或定时显示后台任务执行的情况。此类任务界面通常如下:
这里存在一个问题是如何在界面上显示后台线程上的状态数据,也就是多线程如何访问控件。
.NET中的控件并不是线程安全的,因此我们通常是用如下方法在界面上显示后台线程的数据:
1 2 3 4 5 6 7 8 | private void Test( string val) { if (txtSuccess.InvokeRequired) { txtSuccess.Invoke((ShowVal)Test,val); } else { txtSuccess.Text = val; } } |
此类方法存在一些问题:
1,更新代码比较多,且比较晦涩难懂,不易维护;
2,如果后台状态经常发生变动,则涉及到需要更改的代码可能比较多,如赋值代码,相关委托;
3,后台线程中除了维护状态外还需显世更新前台界面,造成后台线程代码冗余;
那么有没有一种比较好的解决方法呢?答案就是数据绑定。通过数据绑定,后台线程只需要维护任务状态而不需要关心这些数据如何显示,而前台界面仅需要不断更新显示数据,而不必关心数据更新来自何方。
下面以一个简单的例子说明如何利用数据绑定(DataBinding)简化多线程数据展示,假设后台有2个线程在不断处理任务,同时记录了任务执行成功,失败的情况,前台则需要动态显示这些任务的执行状况。任务类简单定义为:
1 2 3 4 5 6 7 8 9 | public class TaskEntity { private int _TaskId = 0; private int _TaskSuccess = 0; private int _TaskFail = 0; public int TaskId { get { return _TaskId; } set { _TaskId = value; } } public int TaskSuccess { get { return _TaskSuccess; } set { _TaskSuccess = value; } } public int TaskFail { get { return _TaskFail; } set { _TaskFail = value; } } public int TaskAll { get { return _TaskSuccess + _TaskFail; } } } |
然后定义一个全局的数据源用于存放这些任务的引用,同时将该数据源邦定到前台界面上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public List<TaskEntity> dataSource; private TaskEntity task1; private TaskEntity task2; private void InitializeDataSource() { dataSource = new List<TaskEntity>(); task1 = new TaskEntity(); task1.TaskId = 0; dataSource.Add(task1); task2 = new TaskEntity(); task2.TaskId = 1; dataSource.Add(task2); } private void InitializeBinding() { dataGridView1.DataSource = dataSource; txtAll.DataBindings.Add( new Binding( "Text" ,task1, "TaskAll" )); txtFail.DataBindings.Add( new Binding( "Text" , task1, "TaskFail" )); txtSuccess.DataBindings.Add( new Binding( "Text" , task1, "TaskSuccess" )); } |
然后启动2个后台线程
1 2 3 4 5 6 7 8 9 10 11 12 | private Thread thread1; private Thread thread2; void btnBS_Click( object sender, EventArgs e) { workStatus = !workStatus; if (workStatus) { thread1 = new Thread(Dowork1); thread1.Start(); thread2 = new Thread(Dowork2); thread2.Start(); } } |
最后定义数据更新方法
1 2 3 4 5 6 | private void UpdateControlValue() { dataGridView1.Invalidate(); txtAll.DataBindings[0].ReadValue(); txtFail.DataBindings[0].ReadValue(); txtSuccess.DataBindings[0].ReadValue(); } |
做完这些后就可以点击验证,执行结果如下:
最后通过比对2种方法的实现,执行结果,可以得出,在.NET中利用数据绑定(DataBinding)可以简化多线程数据展示,使得代码的可维护性更高,对于新人也更容易入手。当然,示例中也存在一些问题,如更新不及时,帮定数据源有限制等。但是想比解决的问题,这些代价完全可以承受,并且通过添加简单的同步代码就可以解决。
注:如需Demo,请留下邮箱(不知道博客园怎么上传资源 *_*|| );
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?