随心所欲

做个幸福的人
posts - 158, comments - 1617, trackbacks - 28, articles - 0
  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理

这是一个在.net2.0里面新出现的类,用于执行后台比较长的任务而又想能和UI有点操作的应用里面。

普通情况下,你点击一个按钮,去后台执行一个process,如果你想得到结果,就得等这个process结束。通常,可以使用异步执行回调来解决这个问题。现在,backgroundworker给我们实现了这样一种简单的封装,可以把我们的复杂任务交给新的线程去处理,然后继续UI线程。等到我们的任务需要通知UI做什么事情的时候,可以report一下,在其事件里就可以直接使用UI控件,而不需要Control.Invoke去掉用之。

 

有这样一个应用:客户需要把大量数据(需要执行3天)copy到另外一个机器,中间想能看到有多少数据被复制/失败等(实时报道)。

 

在这个例子里面,我们的界面可能非常简单:一个开始按钮,一个结束按钮,一个richtextBox来显示运行记录。但是后台执行可能就会比较棘手。如果简单的执行,并且报告,那么整个界面将失去响应(都在同一个线程里面,造成忙碌)。这时候,可以使用这个backgroundworker了。它可以在后台执行,并且报告给界面实时信息,界面不会失去响应。

 

   先介绍一下backgroundworker的几个属性/方法

   .WorkerReportsProgress:是否可以向外报告进度。

   .WorkerSupportsCancellation :是否可以暂停任务

   . CancellationPending: 是否正在暂停中

   . RunWorkerAsync() : 开始执行任务。触发DoWork事件

   . ReportProgress(int percentPrgress,object userState) : 向外报告进度。触发ProgressChanged事件.其中,参数可以在ProgressChangedEventArgsworker_ProgressChanged(object sender, ProgressChangedEventArgs e))中得到

   . CancelAsync() :取消(暂停)执行。

   事件

    worker.DoWork += new DoWorkEventHandler(worker_DoWork);//执行任务

  worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);//任务结束时

    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged)//报告状态

 

   按照上边的资料,我们这个应用就可以这样处理之

   formDisplay是用于显示实时状态的窗口。有DisplyMessage方法来显示信息到界面

   Hanlder类(处理文件copy的)里面:

       static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)

        {

            //show the message on windows

           formDisplay.DisplyMessage(copy, e.UserState.ToString());//show message.

        }

 

        static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

        {

             string msg = "JOB copy : have been completed";

             formDisplay.DisplyMessage(msg);//show message

        }

         

        static void worker_DoWork(object sender, DoWorkEventArgs e)

        {

            for()

            {

                 //copying

                (sender as BackgroundWorker). ReportProgress(0,xxx complete);//report

}

        }

这样构造的程序里面,才不会出现UI失去响应。

 

当然,通过写自己的异步处理也可以实现,功能更强大。只不过这个用起来更简单。

至于backgroundworker是怎么实现的呢?这里有人已经做出了一些解答:

http://blog.joycode.com/sunmast/archive/2006/03/02/about_system_componentmodel_asyncoperation.aspx

Feedback

#1楼  回复 引用 查看   

2006-12-07 13:12 by 高海东      
这个功能很有用

#2楼  回复 引用 查看   

2006-12-07 13:30 by 喝酒的猫      
good!

#3楼  回复 引用 查看   

2006-12-07 13:34 by flyingchen      
http://www.cnblogs.com/flyingchen/archive/2006/07/05/443078.html

#4楼[楼主]  回复 引用 查看   

2006-12-07 13:49 by 随心所欲      
@flyingchen
看过这个了,我觉得还是有必要再写一点。

#5楼  回复 引用   

2006-12-07 14:09 by eee[未注册用户]
好像backGroundWorker存在大bug

#6楼[楼主]  回复 引用 查看   

2006-12-07 14:37 by 随心所欲      
@eee
what the bug is?

#7楼  回复 引用 查看   

2006-12-07 22:28 by flyingchen      
@eee
关心ing!

@随心所欲
支持!

#8楼[楼主]  回复 引用 查看   

2006-12-07 22:48 by 随心所欲      
@flyingchen
小技巧而已,不值一哂。

写blog的有两类人,一是自恋的,二是忘性大的。
年龄渐长,觉得很多东西已经记不住了,就得写下来,留个备份。

#9楼  回复 引用 查看   

2006-12-08 08:55 by flyingchen      
@随心所欲
你这么一说,真让小弟无地自容阿:(

#10楼[楼主]  回复 引用 查看   

2006-12-08 09:27 by 随心所欲      
@flyingchen
呵呵,你多想了。
只是自嘲我的记忆力而已。

#11楼  回复 引用   

2007-02-05 11:02 by net[未注册用户]
好文收藏

#12楼  回复 引用 查看   

2007-07-09 16:39 by jambol      
我已经存到我的BLOG了,谢谢;)
“年龄渐长,觉得很多东西已经记不住了,就得写下来,留个备份。”--还得加上一个,“懒得自己写转别人的”;)

#13楼[楼主]  回复 引用 查看   

2007-07-11 10:07 by 随心所欲      
@jambol
这个东东确有一个bug。
在长时间运行中,可能会出现程序崩溃。
解决方法:设置一个定时任务,时常检查程序状态。

#14楼  回复 引用 查看   

2010-11-25 14:14 by Flynn2009      
@随心所欲
最近在研究这个,你说的崩溃能举个例子吗?比如在什么情况下会崩溃?导致的原因?最好有个代码例子。

#15楼[楼主]  回复 引用 查看   

2010-11-25 14:19 by 随心所欲      
@Flynn2009
原因不详。
有个程序运行了几年了,似乎也没有问题。但是初期的时候奔溃过,怀疑是线程内出现了异常。

#16楼  回复 引用 查看   

2011-05-04 17:11 by weblogical      
假设我操作 100条数据,在50条的时候
我backgroundWorker1.CancelAsync();之后 再次启动,程序是重新开始的 不是从51开始的
Google