首页 > 学院 > 开发设计 > 正文

winform+BackgroundWorker 多线程下如何停止和暂停

2019-11-11 03:26:30
字体:
来源:转载
供稿:网友

本文主要记录如何利用winform,BackgroundWorker线程控件和PRogressBar进度控件进行开发(这样启用工作线程和UI主线程,可以让进度条能进行更新,避免UI假死),同时支持启用多个后台BackgroundWorker,以及支持统一的全局进度条更新,同时支持暂停和停止任务。

下面是定义BackgroundWorker各种事件:

BackgroundWorker  Bworker = new BackgroundWorker();                 Bworker.WorkerReportsProgress = true;Bworker.DoWork += new DoWorkEventHandler(worker_DoWork);Bworker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);Bworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);Bworker.RunWorkerAsync();

在work_DoWork中调用具体执行的方法,worker_ProgressChanged方法用来实时更新进度条值,worker_RunWorkerCompleted方法用来处理当后台线程执行完操作后要处理的事情,如更新界面UI进度条等。

刚开始的时候是没有取消按钮的,现在看看怎么加上取消按钮。

BackgroundWorker 是支持取消事件的,主要通过一个button_click事件,调用Bworker .CancelAsync(),然后在worker_DoWork中检测是否已经取消了:

//检测是否被取消了if (worker.CancellationPending) {    e.Cancel = true;    break; }

       有了取消,就想起了也需要加上暂停,暂停的功能需要自己实现。其实就是利用ManualResetEvent 允许线程通过发信号互相通信的特点,

1.设定一个全局的变量,  public static ManualResetEvent mre = new ManualResetEvent(false);ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。

2.增加一个暂停Pause_Click事件,如果是暂定,则调用 mre.Reset();//暂停当前线程的工作,发信号给waitOne方法,阻塞。

   如果是继续,则 mre.Set();//继续某个线程的工作,

   worker_DoWork中检测mre.WaitOne();这样就完成了简单的暂停控制。

     上面还是用单个线程处理事务,速度很慢,CPU,内存,IO都没有充分的利用起来,所以下面就想到了启用多线程,充分利用系统资源。

      那么问题来了,如何结合BackgroundWorker使用多线程呢,后来发现其实一个简单的做法,就是启用多个BackgroundWorker来启动业务,当然,对应的ManualResetEvent也需要有多个。(启用多个BackgroundWorker唯一要注意的是更新全局变量进度的时候,需要针对进度进行加锁)

 private List<ManualResetEvent> lstManualResets = null; private BackgroundWorker Bworker = null; private static readonly object objLock = new object();
   for (int i = 0; i < nThreadNum; i++)            {                Bworker = new BackgroundWorker();                Bworker.WorkerSupportsCancellation = true;                Bworker.WorkerReportsProgress = true;                Bworker.DoWork += new DoWorkEventHandler(worker_DoWork);                Bworker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);                Bworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);                lstBworkers.Add(Bworker);                lstManualResets.Add(new ManualResetEvent(true));                Bworker.RunWorkerAsync(i);            }

一个临时转换工具的开发过程,记录下来,如上有什么更好建议或想法,也请大家多多指点。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表