MFC下一个通用非阻塞的等待执行结束的对话框类
头文件:CPictureEx用于显示一个等待动画
#pragma once
#include "afxwin.h" #include "resource.h" #include "PictureEx.h" #include <thread> // CWaitDlg 对话框
class CWaitSingleEvent {
public:
CWaitSingleEvent()
: handle_(nullptr){
handle_ = CreateEvent(nullptr, TRUE, FALSE, nullptr);
} ~CWaitSingleEvent(){
if(handle_) {
CloseHandle(handle_);
}
} operator bool()const{
return handle_ != nullptr;
} int Wait(const DWORD wait_time) {
DWORD retval = ;
if(handle_) {
retval = WaitForSingleObject(handle_, wait_time);
ResetEvent(handle_); }
return retval;
} void Notify() {
if(handle_) {
SetEvent(handle_);
}
} protected:
CWaitSingleEvent(const CWaitSingleEvent& rhs){ } CWaitSingleEvent& operator=(const CWaitSingleEvent& rhs){
return *this;
}
private:
HANDLE handle_;
}; typedef UINT32 (CDialogEx::*WaitToExec)(void* param); class CWaitDlg : public CDialogEx
{
DECLARE_DYNAMIC(CWaitDlg) public:
CWaitDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CWaitDlg(); // 对话框数据
enum { IDD = IDD_DIALOG4 }; //设置执行等待函数
void SetWaitToExec(CWnd* pParent, void* pInnerParam, CDialogEx* pThis, WaitToExec pWaitToExec); private:
void* exec_inner_param_;
CDialogEx* dialog_this;
WaitToExec wait_to_exec_func_pt_; volatile bool is_quit_thread_;
std::thread* wait_to_exec_thread_;
CWaitSingleEvent wait_to_exec_condition_; void wait_to_exec_callback(); protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
CPictureEx m_show_gif_;
virtual void OnCancel();
virtual void OnOK();
};
代码实现:
// WaitDlg.cpp : 实现文件
// #include "stdafx.h"
#include "WaitDlg.h"
#include "afxdialogex.h" // CWaitDlg 对话框 IMPLEMENT_DYNAMIC(CWaitDlg, CDialogEx) CWaitDlg::CWaitDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CWaitDlg::IDD, pParent), wait_to_exec_func_pt_(nullptr), dialog_this(nullptr)
{
is_quit_thread_ = false;
exec_inner_param_ = NULL;
wait_to_exec_thread_ = nullptr;
} CWaitDlg::~CWaitDlg()
{
is_quit_thread_ = true;
wait_to_exec_condition_.Notify(); if (nullptr != wait_to_exec_thread_){
if(wait_to_exec_thread_->joinable()) {
wait_to_exec_thread_->join();
} wait_to_exec_thread_ = nullptr;
}
} void CWaitDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SHOW_GIF, m_show_gif_);
} BEGIN_MESSAGE_MAP(CWaitDlg, CDialogEx)
END_MESSAGE_MAP() // CWaitDlg 消息处理程序
BOOL GetResGifSize(long nResId, LPCTSTR name, long *lnWidth, long *lnHeight)
{
HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(nResId), name);
if (NULL == hRsrc) {
return FALSE;
} DWORD dwSize = SizeofResource(NULL, hRsrc);
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if (NULL == hGlobal) {
CloseHandle(hRsrc);
return FALSE;
} unsigned char* pBuffer = (unsigned char*)LockResource(hGlobal);
if (NULL == pBuffer) {
CloseHandle(hRsrc);
FreeResource(hGlobal);
return FALSE;
} //判断是否为GIF文件
if(pBuffer[] != 0x47 && pBuffer[] != 0x49 && pBuffer[] != 0x46 && pBuffer[] != 0x38){
return FALSE;
} //读取宽高
for(DWORD i = ; i < dwSize ; i++)
{
if(pBuffer[i] == 0x00 && pBuffer[i+] == 0x2c)
{
*lnWidth = (pBuffer[i+]<<) | pBuffer[i+];
*lnHeight = (pBuffer[i+]<<) | pBuffer[i+];
UnlockResource(hGlobal);
FreeResource(hGlobal);
return TRUE;
}
} UnlockResource(hGlobal);
FreeResource(hGlobal); return FALSE;
} BOOL CWaitDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); //设置窗口大小
long nGifWidth = ;
long nGifHeight = ;
if (!GetResGifSize(IDR_WAIT_GIF_1, _T("GIF"), &nGifWidth, &nGifHeight)){
MessageBox(_T("内部错误"),_T("错误"), MB_OK | MB_ICONERROR);
} RECT rt;
GetClientRect(&rt); //判断窗口是否太大,或者太小,放不下
if ( (rt.right - rt.left - nGifWidth > ) || (rt.bottom - rt.top - nGifHeight > ) ||
(rt.right - rt.left < nGifWidth) || (rt.bottom - rt.top < nGifHeight) ) {
RECT rtWin;
GetWindowRect(&rtWin); //调整窗口大小
rtWin.right = rtWin.left + nGifWidth + ;
rtWin.bottom = rtWin.top + nGifHeight + ;
MoveWindow(&rtWin); //重新获取客户区大小
GetClientRect(&rt);
} CenterWindow(); //计算位置
rt.left = (rt.right - rt.left - nGifWidth)/;
rt.right = rt.left + nGifWidth;
rt.top = (rt.bottom - rt.top - nGifHeight)/;
rt.bottom = rt.left + nGifHeight; //转化成屏幕坐标
//ClientToScreen(&rt);
m_show_gif_.MoveWindow(&rt, TRUE); SetBackgroundColor(RGB(,,), TRUE);
m_show_gif_.SetBkColor(RGB(,,));
if (m_show_gif_.Load(MAKEINTRESOURCE(IDR_WAIT_GIF_1),_T("GIF"))){
m_show_gif_.Draw();
} return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
} void CWaitDlg::wait_to_exec_callback()
{
if(is_quit_thread_) {
return ;
}
while (!is_quit_thread_){ //等待事件是否过来
wait_to_exec_condition_.Wait(INFINITE);
if(is_quit_thread_) {break;} //判断参数是否OK
if ((nullptr != dialog_this) && (nullptr != wait_to_exec_func_pt_)){
(dialog_this ->*wait_to_exec_func_pt_)(exec_inner_param_); //执行完一次,那就隐藏一下
if (NULL != m_hWnd)
{
ShowWindow(SW_HIDE);
}
}
}
} //设置执行等待函数
void CWaitDlg::SetWaitToExec(CWnd* pParent, void* pInnerParam, CDialogEx* pThis, WaitToExec pWaitToExec)
{
exec_inner_param_ = pInnerParam;
dialog_this = pThis;
wait_to_exec_func_pt_ = pWaitToExec; //通知线程执行
is_quit_thread_ = false; if (wait_to_exec_thread_ == nullptr) {
wait_to_exec_thread_ = new std::thread;
}
if(!wait_to_exec_thread_->joinable()) {
*wait_to_exec_thread_ = std::move(std::thread(&CWaitDlg::wait_to_exec_callback, this));
}
//显示本窗口
if (NULL == m_hWnd) {
Create(IDD_DIALOG4, pParent);
} ShowWindow(SW_SHOW); //触发事件
wait_to_exec_condition_.Notify();
} void CWaitDlg::OnCancel()
{
// TODO: 在此添加专用代码和/或调用基类 //CDialogEx::OnCancel();
} void CWaitDlg::OnOK()
{
// TODO: 在此添加专用代码和/或调用基类 //暂时允许关闭
CDialogEx::OnOK();
}
使用示例:
typedef struct set_xxx_info_st {
int index;
CString strXxxInfo;
}set_xxx_info_st;
void CXXXParamDlg::OnClickedBtnWriteXxx()
{
CString strXxxC = _T("strXxxC");
// 必须使用堆内存,调用会立即返回,但对象的使用,却在线程中
set_xxx_info_st* inn_param = new set_xxx_info_st;
inn_param->index = m_set_cert_index_combo_.GetCurSel() + ;
inn_param->strXxxInfo.Append(strXxxC);
//调用线程接口去获取
m_wait_dlg_.SetWaitToExec(GetParent(), inn_param, this, (WaitToExec)&CXXXParamDlg::WaitToExecSetXXXInfo);
}
UINT32 CXXXParamDlg::WaitToExecSetXXXInfo(void* inn_param)
{
UINT32 ulRet = -;
set_xxx_info_st* set_param = (set_xxx_info_st*)(inn_param);
//禁止父窗口控件
GetParent()->GetParent()->EnableWindow(FALSE);
//设置进去
ExecSetXXX(set_param->index, set_param->strXxxInfo);
//禁止父窗口控件
GetParent()->GetParent()->EnableWindow(TRUE);
if (nullptr != set_param) {
delete set_param;
}
return ;
}
MFC下一个通用非阻塞的等待执行结束的对话框类的更多相关文章
- CompletionService异步非阻塞获取并行任务执行结果
第1部分 问题引入 <Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Execut ...
- 正常断开连接情况下,判断非阻塞模式socket连接是否断开
摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html 在UNIX/LINUX下, 1,对于主动关闭的SOCKET, recv返回-1,而且 ...
- epoll水平/边缘触发模式下阻塞/非阻塞EPOLLOUT事件触发条件及次数
在IO多路复用技术中,epoll默认的事件触发模式为Level_triggered(水平触发)模式,即当被监控的文件描述符上有可读/写事件发生时,epoll_wait()会通知处理程序去读写.如果这次 ...
- 【MPI学习4】MPI并行程序设计模式:非阻塞通信MPI程序设计
这一章讲了MPI非阻塞通信的原理和一些函数接口,最后再用非阻塞通信方式实现Jacobi迭代,记录学习中的一些知识. (1)阻塞通信与非阻塞通信 阻塞通信调用时,整个程序只能执行通信相关的内容,而无法执 ...
- C#学习笔记之线程 - 高级主题:非阻塞同步
非阻塞同步 - Nonblock Synchronization 前面提到,即使在简单的赋值和增加一个字段的情况下也需要处理同步.尽管,使用锁可以完成这个功能,但是锁必定会阻塞线程,需要线程切换,在高 ...
- php非阻塞执行系统命令
大家都知道php调用系统命令常用的主要有以下几种方法: 如exec(), system(), passthru(), shell_exec() 这几个函数的用法在此不做说明,有需要的请查阅php相关手 ...
- Verilog HDL中阻塞语句和非阻塞语句的区别
在Verilog中有两种类型的赋值语句:阻塞赋值语句(“=”)和非阻塞赋值语句(“<=”).正确地使用这两种赋值语句对于Verilog的设计和仿真非常重要. Verilog语言中讲的阻塞赋值与非 ...
- java并发之非阻塞算法介绍
在并发上下文中,非阻塞算法是一种允许线程在阻塞其他线程的情况下访问共享状态的算法.在绝大多数项目中,在算法中如果一个线程的挂起没有导致其它的线程挂起,我们就说这个算法是非阻塞的. 为了更好的理解阻塞算 ...
- Socket阻塞模式和非阻塞模式的区别
简单点说: 阻塞就是干不完不准回来, 非组赛就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系 ...
随机推荐
- 基于maven搭建hibernate运行环境
准备案例需要的数据库表和测试数据 建表语句: create table DEPARTMENT ( DEPT_ID integer not null, DEPT_NAME ) not null, DEP ...
- VB.NET Event RaiseEvent用处
一.代码 Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventA ...
- 开学JAVA第一次测试
定义 ScoreInformation 类,其中包括七个私有变量(stunumber,name, mathematicsscore, englishiscore,networkscore, datab ...
- MySQL 5.7
博客地址:https://www.cnblogs.com/runningStudy/p/6444047.html mysql官网下载地址:https://downloads.mysql.com/arc ...
- tomcat的内存配置
WEB站点在跑安全测试时,跑一会儿就连接不上,考虑是否是tomcat内存溢出问题. Linux环境,修改Tomcat的内存配置: 修改bin/catalina.sh文件,在cygwin=false前面 ...
- 【leetcode】523. Continuous Subarray Sum
题目如下: 解题思路:本题需要用到这么一个数学定理.对于任意三个整数a,b,k(k !=0),如果 a%k = b%k,那么(a-b)%k = 0.利用这个定理,我们可以对数组从头开始进行求和,同时利 ...
- LeetCode--062--不同路径(python)
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”). 问总共有多 ...
- 863D - Yet Another Array Queries Problem(思维)
原题连接:http://codeforces.com/problemset/problem/863/D 题意:对a数列有两种操作: 1 l r ,[l, r] 区间的数字滚动,即a[i+1]=a[i] ...
- 为什么阿里巴巴要禁用Executors创建线程池?
作者:何甜甜在吗 juejin.im/post/5dc41c165188257bad4d9e69 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadP ...
- linux 阿里云oss命令ossutil64 同步文件
官方使用文档: https://help.aliyun.com/document_detail/120057.html?spm=a2c4g.11186623.4.2.1c35448ak8Ez8e [r ...