C#之BackgroundWorker从简单入门到深入精通的用法总结
需求分析
经常用到的耗时操作,例如:
1、文件下载和上载(包括点对点应用程序传输文件,从网络下载文件、图像等)
2、数据库事务(从数据库读到大量的数据到winform界面中的datagridview里呈现)
3、复杂的本地计算
4、本地磁盘文件访问(读写文件,磁盘文件列表)
……
这些操作在长时间运行时会导致用户界面 (ui) 处于停止响应状态,用户在这操作期间无法进行其他的操作,造成非常差的用户体验,为了不使ui层处于停止响应状态,则可以使用 backgroundworker 类方便地解决这类问题。这个后台的线程处理,可以很好的实现常规操作的同时,还可以及时通知ui当前处理信息的进度等。
msdn的介绍
backgroundworker是.net framework 里用来执行多线程任务的控件,它允许开发人员在一个单独的线程上执行一些操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (ui) 似乎处于停止响应状态。 如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 backgroundworker 类方便地解决问题。
若要在后台执行耗时的操作,请创建一个 backgroundworker,侦听那些报告操作进度并在操作完成时发出信号的事件。 可以通过编程方式创建 backgroundworker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。 如果在 windows 窗体设计器中创建 backgroundworker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
若要为后台操作做好准备,请添加 dowork 事件的事件处理程序。 在此事件处理程序中调用耗时的操作。 若要开始此操作,请调用 runworkerasync。 若要收到进度更新的通知,请处理 progresschanged 事件。 若要在操作完成时收到通知,请处理 runworkercompleted 事件。
有2点需要注意的:
1、由于dowork事件内部的代码运行在非ui线程之上,确保在 dowork 事件处理程序中不操作任何用户界面对象。 而应该通过 progresschanged 和 runworkercompleted 事件与用户界面进行通信。
2、backgroundworker 事件不跨 appdomain 边界进行封送处理。 请不要使用 backgroundworker 组件在多个 appdomain 中执行多线程操作。
最简单示例
准备材料:一个耗时的操作
代码如下,这个就不多解释了:
int isum = 0;
private void button1_click(object sender, eventargs e)
{
for (int i = 0; i <= 100; i++)
{
isum+=i;
system.threading.thread.sleep(300);
}
}
运行一下,拖动程序界面看看,直接卡死了,假死,一会儿,运算完了,就又可以拖动了。现在用backgroundworker来解决这个问题。
为此,我们新建一个windowsform命名为bgwa,拖入一个label命名为lblpercent,一个progressbar命名为pgbpercent,一个button命名为btnstart。
然后,代码:
using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.linq;
using system.text;
using system.threading.tasks;
using system.windows.forms;
namespace bgwa
{
public partial class form1 : form
{
public form1()
{
initializecomponent();
}
private void btnstart_click(object sender, eventargs e)
{
backgroundworker bgwa = new backgroundworker();
bgwa.workerreportsprogress = true;
bgwa.dowork += bgwa_dowork;
bgwa.progresschanged += bgwa_progresschanged;
bgwa.runworkerasync();
}
private void bgwa_dowork(object sender, doworkeventargs e)
{
var bgworker = sender as backgroundworker;
for (int i = 0; i <= 100; i++)
{
bgworker.reportprogress(i);
system.threading.thread.sleep(200);
}
}
private void bgwa_progresschanged(object sender, progresschangedeventargs e)
{
this.pgbpercent.value = e.progresspercentage;
this.lblpercent.text = @"已完成:" + e.progresspercentage.tostring() + @"%";
}
}
}
现在运行一下,点击btnstart,进度条跑起来了,再拖动一下程序界面,这下不会没有响应了,不卡,不假死了吧。good.
持续更新中。。。
推荐阅读
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
C#之BackgroundWorker从简单入门到深入精通的用法总结
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
C#之BackgroundWorker从简单入门到深入精通的用法总结
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select