zoukankan      html  css  js  c++  java
  • MFC【17-3】线程和线程同步化

    17.3小知识点

    17.3.1消息泵

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

     1 void CMFC线程View::OnStartDrawing(void)
     2 {
     3     m_bQuit=FALSE;
     4     for(int i=0;i<NUMELLIPSES&&!m_bQuit;i++)
     5     {
     6         DrawRandomEllipse();
     7         if(!PeekAndPump())
     8             break;
     9     }
    10 }
    11 
    12 
    13 void CMFC线程View::OnStopDrawing(void)
    14 {
    15     m_bQuit=TRUE;
    16 }
    17 
    18 
    19 bool CMFC线程View::PeekAndPump(void)
    20 {
    21     MSG msg;
    22     while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
    23         if(!AfxGetApp()->PumpMessage()){
    24             ::PostQuitMessage(0);
    25             return FALSE;
    26         }
    27     }
    28     LONG 1Idle=0;
    29     while(AfxGetApp()->OnIdle(1Idle++));
    30     return TRUE
    31 }

    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:\WINDOWSNotepad.exe.

     1     STARTUPINFO si;
     2     ::ZeroMemory(&si,sizeof(STARTUPINFO));
     3     si.cb=sizeof(STARTUPINFO);
     4     PROCESS_INFORMATION pi;
     5 
     6     if(::CreateProcess(NULL,_T("C:\Windows\Notepard"),NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,
     7         NULL,NULL,&si,&pi)){
     8             ::CloseHandle(pi.hThread);
     9             ::CloseHandle(pi.hProcess);
    10     }

    ::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
    "));
        return(UINT) -1;
    }
        while(){
            ::WaitForSingleObject(hChange,INFINITE);
            ::PostMessage(hwnd,WM_USER_CHANGE_NOTIFY,0,2);
            ::FindNextChangeNotification(hChange);//Reset
        } 
        ::FindCloseChangeNotification(hChange);
        return 0;
    }
  • 相关阅读:
    postman-3http请求
    postman-2get发送请求
    postman-1版本区别、选择
    mysql-13处理重复数据
    mysql-12序列使用
    mysql-11元数据
    mysql-10临时表、复制表
    10)global预定义变量
    9)用request方式
    8)post方式提交和简单那处理
  • 原文地址:https://www.cnblogs.com/fastcam/p/4902819.html
Copyright © 2011-2022 走看看