• 在自动化设备中,设备在运转过程中,为了防止设备伤人,通常会在设备门入口安装光幕,当光幕被遮挡时,设备必须暂停,确保安全的情况下,按下继续按钮,设备继续运转。对于多工位的设备,每个工位可能交由一个线程处理,因此暂停时,需要令这些线程暂时挂起。
  • C++11标准以后,加入了线程相关的接口,在应用中经常需要使线程暂停,在windows API中可以使用suspend 使线程挂起,但容易产生一些意想不到的问题,官方并不推荐使用。但 C++11 中没有使线程暂停的接口。现用条件变量与互斥锁封装一个线程类,实现线程的暂停、继续。
//头文件 Thread.h
#pragma once
#include <thread>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <functional>
class Thread
{public:Thread(std::function<void(int)>func, int workID);virtual ~Thread();enum State{Stoped,     ///<停止状态,包括从未启动过和启动后被停止Running,    ///<运行状态Paused      ///<暂停状态};State state() const;void start();void stop();void pause();void resume();
public://检查线程是否退出bool check_stop();//如果暂停,需要阻塞bool wait_pause();
private:void run();std::function<void(int)> process;
private:int _workID;std::thread* _thread;std::mutex _mutex;std::condition_variable _condition;volatile std::atomic_bool _pauseFlag;   ///<暂停标识volatile std::atomic_bool _stopFlag;   ///<停止标识State _state;
};
//源文件 Thread.cpp
#include "Thread.h"
Thread::Thread(std::function<void(int)> func, int workID): _thread(nullptr),_pauseFlag(false),_stopFlag(false),_state(Stoped),_workID(workID)
{process = func;
}Thread::~Thread()
{stop();
}Thread::State Thread::state() const
{return _state;
}void Thread::start()
{if (_thread == nullptr){_thread = new std::thread(&Thread::run, this);_pauseFlag = false;_stopFlag = false;_state = Running;}
}void Thread::stop()
{if (_thread != nullptr){_pauseFlag = false;_stopFlag = true;_condition.notify_all();  // Notify one waiting thread, if there is one.if (_thread->joinable())_thread->join(); // wait for thread finisheddelete _thread;_thread = nullptr;_state = Stoped;}
}void Thread::pause()
{if (_thread != nullptr){_pauseFlag = true;_state = Paused;}
}void Thread::resume()
{if (_thread != nullptr){_pauseFlag = false;_condition.notify_all();_state = Running;}
}void Thread::run()
{process(_workID);_pauseFlag = false;_stopFlag = false;
}//检查线程是否退出
bool Thread::check_stop()
{return _stopFlag;
}
//如果暂停,需要阻塞
bool Thread::wait_pause()
{if (_pauseFlag){std::unique_lock<std::mutex> locker(_mutex);while (_pauseFlag){_condition.wait(locker); // Unlock _mutex and wait to be notified}locker.unlock();}return !_stopFlag;
}

创建一个MFC的对话框工程,添加按钮如下:

在 OnInitDialog() 函数中添加如下代码创建一个线程

int workID = 1;
pThread = std::make_shared<Thread>(std::bind(&CthreadTest2Dlg::process, this, std::placeholders::_1), workID);

在对话框类中添加线程响应函数

void CthreadTest2Dlg::process(int workID)
{int work = workID;int g_count = 0;while (!pThread->check_stop()){std::this_thread::sleep_for(std::chrono::milliseconds(100));SetDlgItemInt(IDC_COUNT, g_count++);pThread->wait_pause();}g_count = 0;SetDlgItemInt(IDC_COUNT, g_count);
}

开始、继续、暂停和停止按钮响应函数

void CthreadTest2Dlg::OnBnClickedStart()
{pThread->start();
}
void CthreadTest2Dlg::OnBnClickedPause()
{pThread->pause();
}
void CthreadTest2Dlg::OnBnClickedStop()
{pThread->stop();
}
void CthreadTest2Dlg::OnBnClickedContinue()
{pThread->resume();
}

运行程序,单击开始后,编辑框中正常计数,但在线程退出时,阻塞在 join() 函数。经过调试发现MFC的函数 SetDlgItemInt 会影响join()的等待信号。将编辑框的数据直接写入改成post消息后正常。

void CthreadTest2Dlg::process(int workID)
{int work = workID;int g_count = 0;while (!pThread->check_stop()){std::this_thread::sleep_for(std::chrono::milliseconds(100));PostMessage(WM_TEST_MSG, g_count++, NULL);pThread->wait_pause();}g_count = 0;
}

工程下载

C++多线程启动、暂停、继续与停止相关推荐

  1. 多线程启动停止暂停继续

    -Begin- 前言 初学者学习编程时,很容易因为多线程出现各种问题,导致不敢使用多线程.但是多线程技术在做开发中,是不可忽视的一个技术,基本上我们实际应用中,每个项目都会使用多线程,所以多线程技术必 ...

  2. C# Task 多线程 开始 暂停 停止

    C# Task 多线程 开始 暂停 停止 public partial class Form1 : Form{private ManualResetEvent ma;private Cancellat ...

  3. 线程的启动暂停和终止

    线程的启动暂停和终止,听起来很简单,不过经常有初学者在这个问题上卡住,经常是启动了,能暂停,但再要启动就不行了,其实这个问题比较容易解决,思路也很简单,就是在启动线程的时候用一个判断语句锁定整个run ...

  4. python多线程控制暂停_python中的多线程编程与暂停、播放音频的结合

    我们都知道python中可以是threading模块实现多线程, 但是模块并没有提供暂停, 恢复和停止线程的方法, 一旦线程对象调用start方法后, 只能等到对应的方法函数运行完毕. 也就是说一旦s ...

  5. linux启动,重启,停止 jar,.sh脚本

    linux启动,重启,停止 jar,.sh脚本 #配置jar名称 APP_NAME=receiver.jar#使用说明,用来提示输入参数 usage() { echo "Usage: sh ...

  6. java线程开启不了_Java中多线程启动,为什么调用的是start方法,而不是run方法?...

    前言 大年初二,大家新年快乐,我又开始码字了.写这篇文章,源于在家和基友交流的时候,基友问到了,我猛然发现还真是这么回事,多线程启动调用的都是start,那么为什么没人掉用run呢?于是打开我的ide ...

  7. tungsten开机启动及进程开启停止

    tungsten开机启动及进程开启停止 posted on 2014-06-24 09:33 秦瑞It行程实录 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblog ...

  8. Java中多线程启动,为什么调用的是start方法,而不是run方法?

    前言 大年初二,大家新年快乐,我又开始码字了.写这篇文章,源于在家和基友交流的时候,基友问到了,我猛然发现还真是这么回事,多线程启动调用的都是start,那么为什么没人掉用run呢?于是打开我的ide ...

  9. 媒体控件的播放暂停继续与停止 winform

    媒体控件的播放暂停继续与停止 winform 准备媒体 把媒体放在了一个路径 bin/debug,是项目资源的根目录 播放功能 暂停功能 继续播放 停止播放

  10. c#winform演练 ktv项目 MediaPlay控件的暂停播放与停止

    c#winform演练 ktv项目 MediaPlay控件的暂停播放与停止 用法 媒体控件.Ctlcontrols.操作名() 关于操作名: play,播放 stop,停止 pause,暂停 例子

最新文章

  1. iosanimationWithKeyPath
  2. Android相关面试题---初识
  3. 用js改变embed标签的src值
  4. python udp 传输文件_python网络编程:UDP方式传输数据
  5. PAT1049 数列的片段和 (20 分)
  6. 毕业典礼校长致辞金句频出:搬砖也要元气满满
  7. metal分析是什么意思_变压器原理是什么?容量是什么意思?电力工程技术专家精讲分析...
  8. Linux基础命令--grep/find
  9. 呼吁各行业实现无纸化办公
  10. 微信小程序开发部署发布可以在10分钟内完成
  11. 【Java加密】JCA体系结构
  12. “龙书”作者Jeffery Ullman:相信你自己,自由地思考
  13. 大规模知识图谱数据存储实战解析
  14. ISO9000中服装加工行业应执行哪些检验标准?
  15. 旅行青蛙分析(Android篇)
  16. 进程间同步---system v ipc 对象信号灯集
  17. [转帖] 丰富多彩的开放课程资源
  18. Note of Numerical Optimization Ch.3
  19. 盒子读取服务器视频文件,电视盒子怎么看U盘里的视频?巧用当贝市场,教你一招轻松搞定...
  20. python做系统辨识_python实现一般最小二乘系统辨识方法

热门文章

  1. matlab-采用For循环,将每次计算得到的矩阵,依次放进一个新的矩阵
  2. git的使用(github篇)
  3. Java和go加密,解密,Base64失败
  4. cadence 批量一次性修改title 页码标题等
  5. umi+dva dva全局的dispatch方法
  6. Word中㎡的上标²变成了2该如何处理
  7. 互联网产业中“外行领到内行”和软件工程
  8. 曾经最好用的浏览器凉了?正在被大批网站抛弃
  9. Android PULL XML Praser
  10. Android UnitTest