BackgroundWorker bw;
private ManualResetEvent manualReset = new ManualResetEvent(true); private void button3_Click(object sender, EventArgs e)
{
using ( bw = new BackgroundWorker())
{
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.DoWork += bw_DoWork; //允许用户指定显示数据的范围呢!所以需要把100作为参数传递给计算过程
bw.RunWorkerAsync();
} }
//这时返回了主线程,所以可以直接使用UI控件了
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//修改进度条的显示。
//this.progressBarSum.Value = e.ProgressPercentage; //如果有更多的信息需要传递,可以使用 e.UserState 传递一个自定义的类型。
//这是一个 object 类型的对象,您可以通过它传递任何类型。
//我们仅把当前 sum 的值通过 e.UserState 传回,并通过显示在窗口上。
string message = e.UserState.ToString();
label1.Text = message;
}
//e.Argument=bw.RunWorkerAsync("Hello World")的参数
void bw_DoWork(object sender, DoWorkEventArgs e)
{
System.Diagnostics.Debug.WriteLine("bw_DoWork"); BackgroundWorker bgWorker = sender as BackgroundWorker; //这里的操作是在另一个线程上完成的,不应该操作UI
//在这里执行耗时的运算。 int endNumber = ;
if (e.Argument != null)
{
endNumber = (int)e.Argument;
} for (int i = ; i <= endNumber; i++)
{
manualReset.WaitOne();
//如果ManualResetEvent的初始化为终止状态(true),那么该方法将一直工作,
//直到收到Reset信号。然后,直到收到Set信号,就继续工作。 bgWorker.ReportProgress(i, "current num:" + i.ToString());
Thread.Sleep(); //为了方便演示
if (bgWorker.CancellationPending)
{
e.Cancel = true;
System.Diagnostics.Debug.WriteLine("CancellationPending");
break;
} } }
//停止
private void button4_Click(object sender, EventArgs e)
{
bw.CancelAsync();
}
//暂停/继续
private void button5_Click(object sender, EventArgs e)
{
if (btnPause.Text == "暂停")
{
manualReset.Reset();//暂停当前线程的工作,发信号给waitOne方法,阻塞
btnPause.Text = "继续";
}
else
{
manualReset.Set();//继续某个线程的工作
btnPause.Text = "暂停";
}
}

请注意红色字体, 采用信号量 ManualResetEvent来控制暂停/继续

ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

多线程学习笔记(三) BackgroundWorker 暂停/继续的更多相关文章

  1. 多线程学习笔记(二) BackgroundWorker 和 ProgressChanged

    BackgroundWorker是在内部使用了线程池的技术:同时,在Winform 或WPF编码中,它还给工作线程和UI线程提供了交互的能力. Thread和ThreadPool默认都没有提供这种交互 ...

  2. 多线程学习笔记三之ReentrantLock与AQS实现分析

    目录 简介 AQS同步状态 AQS同步队列 ReentrantLock数据结构 公平锁的获取 tryAcquire(arg) addWaiter(Node mode) acquireQueued(fi ...

  3. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  4. [Firefly引擎][学习笔记三][已完结]所需模块封装

    原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读:        笔记三主要就是各个模块的封装了,这里贴 ...

  5. JAVA多线程学习笔记(1)

    JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...

  6. 学习笔记(三)--->《Java 8编程官方参考教程(第9版).pdf》:第十章到十二章学习笔记

    回到顶部 注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法 ...

  7. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  8. muduo网络库学习笔记(三)TimerQueue定时器队列

    目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...

  9. java进阶-多线程学习笔记

    多线程学习笔记 1.什么是线程 操作系统中 打开一个程序就是一个进程 一个进程可以创建多个线程 现在系统中 系统调度的最小单元是线程 2.多线程有什么用? 发挥多核CPU的优势 如果使用多线程 将计算 ...

随机推荐

  1. 6.python3实用编程技巧进阶(一)

    1.1.如何在列表中根据条件筛选数据 # 1.1.如何在列表中根据条件筛选数据 data = [-1, 2, 3, -4, 5] #筛选出data列表中大于等于零的数据 #第一种方法,不推荐 res1 ...

  2. 3. Go语言—函数和常量

    一.函数声明和注释 1. 声明 ​ func 函数名 (参数列表)(返回值列表){} func add{ pass } func add(a int, b int){ } func add(a int ...

  3. NOI2015 软件包管器

    NOI2015 软件包管器 https://www.luogu.org/problem/P2146 题意 维护一棵树,每个节点都有一个为0或1的值,初始值全为0 需要支持 将一条链上的点都变成1, 将 ...

  4. Javascript定时器只能执行一次

    为了说明问题,代码很短 <script> var test = function(){ console.log('a') } timer1 = setInterval(test(), 10 ...

  5. layer之关闭弹窗

    一. layer关闭弹出层方法1-1) 先获取某个弹出层的 index var index = layer.open();   var index = layer.alert(); var index ...

  6. SQL Server 迁移数据库 (四)备份和还原

    1. 备份 2. 复制 3. 粘贴 4. 还原 截图软件出问题了,估计重启下就好,但是备份还原比较简单,懂的都懂,马上下班了就不贴图了.

  7. linux下如何查看自己都装了什么服务

    service --status-all 先把rabbitmq进程杀掉 ps -ef | grep rabbitmq | grep -v grep | awk '{print $2}' | xargs ...

  8. iOS:获取一周7天的日期(年-月-日-星期)

    一.介绍 在开发中,日期的使用绝对是离不了的,跟业务的关联性太强了,例如课程表.有的时候我们不需要课程表,但是需要获取一周7天的日期,这一周内的日期,我觉得有两种理解: 1.获取当天开始的一周日期,当 ...

  9. python-7-数据结构与类型转换

    前言 python除了前面所说的基础类型,我们这里也需要讲解下数据结构,数据结构里面存放的是基础类型,如数字等同时也可以嵌套. 不可变数据(3 个):Number(数字).String(字符串).Tu ...

  10. 局域网部署ntp时间服务器

    搭建ntp时间服务器 时间服务器配置 须切换到root用户,再进行操作 检查ntp是否安装 [root@hadoop01 ~]# rpm -qa | grep ntp 如果没有安装,须安装 [root ...