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. C# Session 操作类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. Shell命令-系统信息及显示之df、top

    文件及内容处理 - df.top 1. df:报告文件系统磁盘空间的使用情况 df命令的功能说明 df 命令用于显示目前在Linux系统上的文件系统的磁盘使用情况统计. df命令的语法格式 df [O ...

  3. fiddler---Fiddler查看get和post请求

    前几篇写了Fiddler的一些功能介绍,今天我们一起学习下如何通过fiddler查看get请求和post请求和get,post区别 get请求 1.启动fiddler,抓取安静博客地址 2.通过fid ...

  4. vue+node+elementUI实现注册功能

    后端代码 在后端的文件 routes文件夹下的connect.js文件中 // 引入mysql const mysql = require('mysql'); // 创建连接对象 const conn ...

  5. leetcode 排序问题

    1.堆排序 //大顶堆的构造,传入的i是父节点 void HeapAdjust(int k[],int p,int n) { int i,temp; temp = k[p]; * p; i <= ...

  6. CentOs篇

    Advanced-高级配置.Security-安全.Boot-启动引导: 1.Removable Devices-移动设备 2.Hard Drive-本地硬盘 3.CD-ROM- Drive-光盘 4 ...

  7. Redis集群模式介绍

    前言: 一.为什么要使用redis 1,解决应用服务器的cpu和内存压力 2,减少io的读操作,减轻io的压力(内存中读取) 3,关系型数据库扩展性,不强,难以改变表的结构 二.优点 1,nosql数 ...

  8. mysql 写计数器需要注意的问题

    MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能 由于并发的时候 不能同时写入一行数据 所以要分开写<pre>先创建表CREATE TABLE `article_view` ...

  9. Ubuntu18.04下修改快捷键

    Ubuntu下修改快捷键 Intelij Idea在Ubuntu下的快捷键几乎和windows差不多,最常用的一个快捷键与系统冲突: Ctrl + Alt + T idea是surround with ...

  10. Python platform 模块

    Python platform 模块 platform 模块用于查看当前操作系统的信息,来采集系统版本位数计算机类型名称内核等一系列信息. 使用方法: import platform # 获取操作系统 ...