l Image downloads
l Web service invocations
l File downloads and uploads (including for peer-to-peer applications)
l Complex local computations
l Database transactions
l Local disk access, given its slow speed relative to memory access
这个时候UI就会陷入一种假死的状态,会给用户带来一种很不好的体验. 如何在这里发挥多线程的优势以改善用户体验? .Net2.0的System.ComponentModel.BackgroundWorker为我们提供了一个很方便的解决方法.
在vs.net2005 101 sample中提供了一个计算素数的例子, 不过那个例子并没有全面演示BackgroundWorker的能力, 尤其是没有对线程工作过程(ReportProgress)中的能力做比较好的演示.因此我重新做了一个Demo.
这个例子很简单, 就是将左边列表中的内容移至的右边, 用一个进度条来显示移动的进度, 当然既然是BackgroundWorker这个时候主界面可以进行其他操作.
本文的源代码提供下载, 其中有详细注释, 所以我在此简要介绍一下需要注意的地方.
BackgroundWorker主要通过对DoWork ProgressChanged RunWorkerCompleted三个事件的处理来完成任务. 需要注意在DoWork中不能直接操作主界面的元素.比如你在MainForm类中启动了一个BackgroundWorker, 在DoWork的处理方法中不能直接调用任何MainForm中的成员变量. 但是在ProgressChanged 和 RunWorkerCompleted的事件处理中则无此限制, 可以在后台线程中直接调用主线程中的元素, 这是BackgroundWorker中最有亮点的地方. 虽然在DoWork的处理方法中不能调用但是它也提供了参数传递的方法,可以间接调用.示例如下:
27 //If your background operation requires a parameter,
28 //call System.ComponentModel.BackgroundWorker.RunWorkerAsync
29 //with your parameter. Inside the System.ComponentModel.BackgroundWorker.DoWork
30 //event handler, you can extract the parameter from the
31 //System.ComponentModel.DoWorkEventArgs.Argument property.
32 worker.RunWorkerAsync(leftList);
27 private void worker_DoWork(object sender, DoWorkEventArgs e)
28 {
29 MoveList((BackgroundWorker)sender,e);
30 }
31
32 private void MoveList(BackgroundWorker worker,DoWorkEventArgs e)
33 { //get leftList in Main UI Thread from arguments
34 IList<string> list = e.Argument as IList<string>;
35 //...
36 }
而在ProgressChanged和RunWorkerCompleted事件的处理方法中则更加简单.
27 private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
28 {
29 //Add string to the right listBox, we use rightList in Main UI Thread directly
30 rightList.Add(e.UserState as string);
31 }
上述原则可以说是BackgroundWorker最需要注意的地方.
另外一个容易被人粗心漏过的地方是有关属性的设置.
如果你要使BackgroundWorker支持进度汇报和取消功能别忘了在初始化的时候为下面两个属性赋值.
// Specify that the background worker provides progress notifications
worker.WorkerReportsProgress = true;
// Specify that the background worker supports cancellation
worker.WorkerSupportsCancellation = true;
其它部分就让大家自己看代码吧.
BackgroundWorker内部实现是基于delegate的异步调用.
源代码下载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何统计不同电话号码的个数?—位图法
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 从零实现富文本编辑器#3-基于Delta的线性数据结构模型
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· 基于Blazor实现的运输信息管理系统
· 微信支付功能的设计实现与关键实践(UniApp+Java)全代码
· 用c#从头写一个AI agent,实现企业内部自然语言数据统计分析
· 三维装箱问题(3D Bin Packing Problem, 3D-BPP)
· MCP协议Streamable HTTP