• 线程与进程


    一 . 进度条从头走到尾

    在资源视图中添加Process Control 和 Button 

    控件Process Control右键添加变量,Button双击添加函数如下:

    做法一:

        for(int i = 0; i <= 100; i++)//相对位置,所以要到=100
        {
            m_proctrl.SetPos(i);
        }

    做法二:

        m_proctrl.SetStep(1);//SetStep与StepIt一起使用
        int i = 0;
        while(i++ < 10)
        {
            m_proctrl.StepIt();//默认一次走10进度
        }

    二 . Windowsx消息响应机制

    系统消息对列 ->  当前应用程序的消息对列 -> GetMessage()从对列中取出消息 -> TranslateMessage()翻译函数 -> DispatchMessage()分发函数 ->

    Afxunclproc回调函数(所有的函数都有一个回调函数,即消息入口点函数)---消息发送到窗口---->   pWnd -> windoproc  ----消息映射表-------->  处理函数

     tips:SendMessage()不进入程序的消息对列,但进入系统的消息对列

        while(1)
        {
            proctrl.StepIt();
            sleep(0);//没有效果,因为睡眠时没有其他消息要执行,没有取出消息
            sleep(100);//进度条变缓慢
        }        

    Sleep时,效果,可以执行其他消息吗 ? 进度条变慢:sleep(0);让出本次时间片,sleep(100):睡100s,醒来后再轮转到它才行 。 sleep时可以执行其他消息因为没有从消息对列中拿消息所以不能执行

    下面的做法虽然可以在跑进度条的时候,接收其他消息,但二者不能同时执行,创建线程则可以。

        while(1)
        {
            MSG msg;
            proctrl.StepIt();
            //--------------可以并发处理别的消息------------
            if(GetMessage(&msg,0,0,0))//从队列中取得消息
            {
                TranslateMessage(&msg);//翻译消息
                DispatchMessage(&msg);//分发消息
            }
            //---------并发:轮换时间片,不能同时执行----------
        }

     三 . 创建线程

    线程:进程中的执行单元 , 分配CPU的基本单位。

    线程栈:存储在线程中创建的变量(线程退出,线程栈被销毁掉)

    内核对象:计数器 (初始值为2,当为0时,释放内核对象)1.线程退出(-1)2.关闭句柄(-1)(CloseHandle()) ; openThread()计数器+1

         挂起计数器  :  SuspendThread()挂起计数器+1;ResumeThread()挂起计数器-1

         信号:线程退出则有信号,否则无信号(WAIT_TIMEOUT)。

    void CThreadtestDlg::OnBnClickedButton1()
    {
        //创建线程
        if(!m_hThread)//线程不存在则创建线程
        {
            m_bFlagQuit = true;
          m_hThread = CreateThread(NULL, //安全属性
                      0 ,//线程栈  默认1MB
                      &ThreadProc, //函数地址
                     this, //线程参数
                      0 ,//创建标志  0 立即运行  CREATE_SUSPENDED  挂起
                      NULL //线程ID
               );
        }
        else
        ResumeThread(m_hThread);//线程存在则恢复线程(挂起计数器-1),挂起计数器不能为负
    }

    线程执行的函数

    DWORD WINAPI ThreadProc( LPVOID lpParameter)

    //调用约定
    //WINAPI (C++) stdcall 参数入栈顺序从右--左 函数本身清理
    //WINAPIV (C) cdecl 参数入栈顺序从右--左 由调用者清理空间 支持可变的参数个数

    {
        CThreadtestDlg *pthis = (CThreadtestDlg *)lpParameter;    
        
        while(pthis->m_bFlagQuit)//bool变量,退出时使用,不满足条件则线程退出
        {
            pthis->m_proctrl.StepIt();
            Sleep(100);    
        }  
    
        return 0;
    }

    四  . 暂停按钮(挂起进程)

    void CThreadtestDlg::OnBnClickedButton2()
    {
        SuspendThread (m_hThread);//挂起计数器+1
    }

    五 . 结束按钮(结束进程,关闭句柄)

    void CThreadtestDlg::OnBnClickedButton3()
    {
        //1.正常退出
        m_bFlagQuit = false;
        //2.强制退出
        //ExitThread()退出调用它的线程
        //判断线程是否已经退出,如果没有( 无信号),则强制杀死
        if(WAIT_TIMEOUT ==  WaitForSingleObject(m_hThread,100))
            TerminateThread(m_hThread,-1);
    
        if(m_hThread)
        {
            CloseHandle(m_hThread);//关闭句柄
            m_hThread = NULL;
        }
        m_proctrl.SetPos(0);//进度条归零
    }

     六 . 实现进程间通信(一个进程可以控制另一个进程中进度条的停止)

    进程间用时间进行通信,事件也是系统内核,HANDLE句柄类型。

    在Dialog类中定义一个HANDLE hSignal;

        hSignal = CreateEvent(NULL,//安全属性
                        TRUE,//复位属性(自动/手动)TRUE为人工,FALSE为自动
                        FALSE,//初始化(无信号)
                        _T("Event"));//名字

    在线程执行函数中

    DWORD WINAPI ThreadProc(LPVOID lpParameter)//线程要执行的函数
    {
        CThreadDlg* pthis = (CThreadDlg*)lpParameter;
        while(1)
        {
            if(WAIT_OBJECT_0 == WaitForSingleObject(pthis->hSignal , 100))
                    //等待100ms,事件有信号则返回
                break;
            pthis->proctrl.StepIt();
            Sleep(100);
        }
    
        return 0;
    }

    在go按钮中

        if(!hThread)
        {
            ResetEvent(hSignal);//重置信号(自动则不需要)
            hThread = CreateThread(//多线程,并行:同时执行
                NULL,
                0,//线程栈大小,默认为1M
                &ThreadProc,//进程执行的函数
                this,//传入线程的参数
                0,//立即执行, CREATE_SUSPENDED 挂起执行
                0//进程ID
            );
        }

    在stop按钮中

    void CThreadDlg::OnBnClickedStop()//杀死线程
    {
        //将事件设为有信号
        SetEvent(hSignal);
    
        if(hThread)
        {
            CloseHandle(hThread);
            hThread = 0;
        }
        proctrl.SetPos(0);
    }

    新建项目,放置一个按钮,按钮功能为让另一个进程的进度条线程退出

        HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS , FALSE , _T("Event"));//第一个为权限,第三个为事件名称(唯一)
        if(hEvent)
            SetEvent(hEvent);

    七 . 线程的基本状态:

    阻塞---1--->就绪----2--->执行     1.  获得I/O资源   2.获得时间片

    阻塞<---3----就绪<---4---执行      3.不存在,因为就绪态没办法执行到阻塞     4.时间片用完

    阻塞----5---->执行                        5.不存在

    阻塞<-----6----执行        6.缺少I/O资源

  • 相关阅读:
    标准C程序设计七---17
    标准C程序设计七---16
    标准C程序设计七---15
    标准C程序设计七---14
    标准C程序设计七---13
    标准C程序设计七---12
    标准C程序设计七---11
    标准C程序设计七---10
    标准C程序设计七---07
    java常见文件操作
  • 原文地址:https://www.cnblogs.com/Lune-Qiu/p/8395370.html
Copyright © 2020-2023  润新知