17.3小知识点

17.3.1消息泵

编写一个应用程序,让它响应某菜单命令,画几千个椭圆。

 void CMFC线程View::OnStartDrawing(void)
{
m_bQuit=FALSE;
for(int i=;i<NUMELLIPSES&&!m_bQuit;i++)
{
DrawRandomEllipse();
if(!PeekAndPump())
break;
}
} void CMFC线程View::OnStopDrawing(void)
{
m_bQuit=TRUE;
} bool CMFC线程View::PeekAndPump(void)
{
MSG msg;
while(::PeekMessage(&msg,NULL,,,PM_NOREMOVE)){
if(!AfxGetApp()->PumpMessage()){
::PostQuitMessage();
return FALSE;
}
}
LONG 1Idle=;
while(AfxGetApp()->OnIdle(1Idle++));
return TRUE
}

PeekAndPump在一个消息循环中定制另一个消息循环。它在OnStartDrawing中for语句的循环终点处被调用。如果::PeekMessage指示队列中有消息等待,则PeekAndPump首先调用CWinThread::PumpMessage提取消息和分派消息。如果PumpMessage返回0,则表示提取和分派的最后一个消息是WM_QUIT消息。而因为只有用“主”消息循环提取WM_QUIT消息,应用程序才能结束,所以该消息要求特殊处理。因此如果PumpMessage返回0,PeekAndPump就会把另一个WM_QUIT消息发往队列;如果PeekAndPump返回0,就会把另一个WM_QUIT消息发往队列;如果PeekAndPump返回0,OnStartDrawing中的for语句循环就会失败。如果WM_QUIT消息不提示提前退出,那么通过在返回之前调用应用程序对象的OnIdle函数,PeekAndPump就可以模仿主程序的闲置机制。

17.3.2执行其他进程

Win32执行进程。下列语句执行c:\\WINDOWS\Notepad.exe.

     STARTUPINFO si;
::ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi; if(::CreateProcess(NULL,_T("C:\\Windows\\Notepard"),NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,
NULL,NULL,&si,&pi)){
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
}

::CreateProcess是一个通用函数,它获取可执行文件的名字(和路径),然后加载并执行他,如果可执行文件名中的驱动器和目录名被省略,则系统自动在Windows目录,Windows系统目录,当前路径下的所有目录和选中的其他位置中搜索该文件。文件名也可以包含命令行参数,如:

“C:\\Windows\\Notepad C: \\ Windows\\ Desktop\\Ideas.txt"

::CreatProcess将进程的关键信息填充在PROCESS_INFORMATION结构中。相关信息包括:进程句柄(hProcess)和进程中主线程的句柄(hThread)。在进程启动后,要用::CloseHandle关闭这些句柄。如果CreateProcess返回非零值,则意味着进程启动成功。因为Win32是一部启动、一部执行的,所以CreateProcess不必等到进程结束后再返回。如果您希望启动另一个进程,并暂停当前进程知道该进程启动的进程结束,则您可以对该进程句柄调用::WaitForSingleObject

    STARTUPINFO si;
::ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi; if(::CreateProcess(NULL,_T("C:\\Windows\\Notepard"),NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,
NULL,NULL,&si,&pi)){
::CloseHandle(pi.hThread);
::WaitForSingleObject(pi.hProcess,INFINITE);
::CloseHandle(pi.hProcess);
}

进程和线程一样都有退出代码。如果::WaitForSingleObject没有返回WAIT_FAILED,则可以调用::GetExitCodeProcess获取进程的退出代码。

  有时需要启动进程并等待足够长的时间后,才能确保进程已开始并相应用户输入。例如:如果进程A启动进程B,而进程B又创建了一个窗口,这是,如果进程A要给窗口发送消息,他就不得不等到CreateProcess返回,留给进程B足够的时间创建窗口并开始处理消息。通过Win32::WaitForInputIdle函数可以解决这个问题。

    STARTUPINFO si;
::ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pi; if(::CreateProcess(NULL,_T("C:\\Windows\\Notepard"),NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,
NULL,NULL,&si,&pi)){
::CloseHandle(pi.hThread);
::WaitForInputIdle(pi.hProcess,INFINITE);
::CloseHandle(pi.hProcess);
}

17.3.3文件改变通知

::WaitForSingleObject的HANDLE参数可以是“文件改变通知句柄”。Win32 API包含一个函数::FindFirstChangeNotification,只要给定目录或他的子目录发生了变化,例如文件被重命名或删除,或创建了一个新目录,该函数都能返回一个句柄,通过该句柄您可以启动一个被阻塞的线程。

如果想改善11章中的Wanderer应用程序,使文件系统的而变化难呢过立刻反应在左面或右面的窗格中。为此,最有效的方法是启动一个后台线程,并使它在一个或多个文件改变通知句柄上处于阻塞状态。下面是用来监视驱动器C:的线程的线程函数:

UINT ThreadFunc(LPVOID pParam)
{
HWND hwnd=(HWND)pParam;//Window to notify
HANDLE hChange = ::FindFirstChangeNotification(_T("C:\\"),
TRUE,FILE_NOTIFY_CHANGE_FILE_NAME);// FILE_NOTIFY_CHANGE_DIR_NAME);
if(hChange==INVALID_HANDLE_VALUE){
TRACE(_T("Error:FindFirstChangeNotification failed\n"));
return(UINT) -;
}
while(){
::WaitForSingleObject(hChange,INFINITE);
::PostMessage(hwnd,WM_USER_CHANGE_NOTIFY,,);
::FindNextChangeNotification(hChange);//Reset
}
::FindCloseChangeNotification(hChange);
return ;
}

MFC【17-3】线程和线程同步化的更多相关文章

  1. MFC【17-2】线程和线程同步化

    17-2线程同步 Windows支持4中类型的同步对象,可以用过来同步由并发运行的线程执行的操作: 临界区 互斥量 事件 信号量 MFC在名为CCriticalSection\CMutex\CEven ...

  2. MFC【17-1】线程和线程同步化

    17.1线程 对于Windows来说所有的线程都是一样的,但MFC却把线程区分为两种类型:User Interface(UI) threads(用户界面(UI)线程)和Worker threads(工 ...

  3. C#高级编程笔记(17至21章节)线程/任务

    17 Visual Studio 2013 控制台用Ctrl+F5可以显示窗口,不用加Console.ReadLine(); F5用于断点调式 程式应该使用发布,因为发布的程序在发布时会进行优化, 2 ...

  4. 用MFC库函数AfxBeginThread()来创建线程

    在进行多线程程序设计的时候,我们经常用到AfxBeginThread函数来启动一条线程该函数使用起来非常的简单方便,其定义如下: 1.函数原型 CWinThread* AfxBeginThread( ...

  5. C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

  6. Java线程:线程状态的转换

    Java线程:线程状态的转换   一.线程状态   线程的状态转换是线程控制的基础.线程状态总的可分为五大状态:分别是生.死.可运行.运行.等待/阻塞.用一个图来描述如下:   1.新状态:线程对象已 ...

  7. 基础学习day12--多线程一线程之间的通信和常用方法

    一.线程之间的通信 1.1.线程之间的通信方法 多个线程在处理统一资源,但是任务却不同,这时候就需要线程间通信.    等待/唤醒机制涉及的方法:    1. wait():让线程处于冻结状态,被wa ...

  8. 基础学习day11--多线程一线程的创建,运行,同步和锁

    一.线程基本概述 1.1.进程和线程 进程:一个应用程序一般都是一个进程,正在进行的程序 每一个进程最少都有一个线程,都有一个执行顺序,该顺序是一个执行路径或者一个控制单元 线程:进程中一个独立的控制 ...

  9. C#中的线程(中)-线程同步

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

随机推荐

  1. JMeter 中 HTTP Cookie 管理器的使用

    根据 web 应用的复杂度你可以选择创建两种类型的 JMeter 测试计划:面向点击数的或面向场景的. 创建一个面向点击数的测试计划你需要有中值统计.这些统计要包含你的应用每秒应该处理多少个独立请求的 ...

  2. Two Sum ——经典的哈希表的题

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  3. Go语言标准库之log包

    用来作日志log输出的, 比较易懂. 今天周六啊,在公司加班学习一下呀. package main import ( "log" ) func init() { log.SetPr ...

  4. 画图工具除了echarts我使用highcharts

    文件 :密码:xewx 官方文档教程地址:https://www.hcharts.cn/docs/basic-color 上手容易,api友好,尽管也有不尽人意的地方,但是它很适合我当前的项目,如果想 ...

  5. 解决ssh登录过慢问题

    1.首先打开debug,看看慢在哪里 [root@BC-NFS1 ~]# ssh -v root@192.168.102.41 -p 22 OpenSSH_6.6.1, OpenSSL 1.0.1e- ...

  6. HDU 6280 From Tree to Graph(2018 湘潭邀请 E题,树的返祖边)

    其实打返祖边就相当于$x$到祖先这一段点(不包括两端)答案都要减$1$. 然后每个点最多减$1$次$1$. #include <bits/stdc++.h> using namespace ...

  7. 【转】【python】装饰器的原理

    写在前面: 在开发OpenStack过程中,经常可以看到代码中的各种注解,自己也去查阅了资料,了解了这是python中的装饰器,因为弱类型的语言可以将函数当成返回值返回,这就是装饰器的原理. 虽然说知 ...

  8. Linux基础系列-Day5

    网络管理 ifconfig网络管理工具 ifconfig依赖于命令中使用一些选项属性,不仅可以被用来简单地获取网络接口配置信息,还可以修改这些配置,但是通过ifconfig修改的通常为临时配置,即系统 ...

  9. EasyUI学习总结(五)——EasyUI组件使用(转载)

    本文转载自:http://www.cnblogs.com/xdp-gacl/p/4084520.html 一.EasyUI组件的简单介绍 easyUI提供了很多组件让我们使用,如下图所示:

  10. 【最小割】【Dinic】Gym - 101128F - Landscaping

    http://blog.csdn.net/lxy767087094/article/details/68942422 #include<cstdio> #include<cstrin ...