线程与进程

本文介绍在Windows环境下如何利用线程控制进度条显示,包括两种更新进度条的方法、消息响应机制、线程创建与控制,以及通过事件实现线程间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 . 进度条从头走到尾

在资源视图中添加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资源

转载于:https://www.cnblogs.com/Lune-Qiu/p/8395370.html

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值