• 《Win32多线程程序设计》学习笔记 第11章 GDI 与窗口管理


    Win32中,每个线程都有自己专属的消息队列,并不是每个窗口都有自己的消息队列。因为每个线程能够产生很多窗口,如果一个线程停止响应,或者它忙于一段耗时的计算工作,那么由它差生的窗口统统都会停止响应,但系统中的其他窗口还是继续正常的运作。

    所有传递给某一窗口的消息,将由产生该窗口之线程负责处理。

    对窗口所做的任何一个事情基本上都由该窗口的窗口函数处理,并因此被产生该窗口的线程处理。

    SendMessage()

    同一线程:直接调用窗口函数

    不同线程:切换到新线程并调用窗口函数 ,在该函数返回之前,SendMessage不会返回(所以会发生意Context Switch,比一般函数调用费时间)

    PostMessage()

    同一线程:把消息放入消息队列立即返回

    不同线程:立即返回,消息放入另一线程的消息队列中

     ----------------------------------------------------

    所以如果各个窗口都有自己的线程,那么在处理各个窗口的响应时可能要发生很多次的context switch ,效率低下,所以不能有自己的线程。

    如果一个线程调用了SendMessage后,当前线程就会等待其返回,类似于sleep状态,但是还是可以处理 外界对其窗口的sendMessage操作。

    如果某个线程正在 处理由其他线程Send过来的消息,可以在该线程中调用IsSendMessage,会获得TRUE。为了让调用端线程能够继续工作,我们可以调用ReplyMessage。

    为了防止线程因为SendMessage导致的死锁(永远醒不过来) ,Win32提供2个函数。第一个是SendMessageTimeout,允许你指定一个时间,时间终了了一定会返回。第二个是SendMessageCallback。这个函数会立刻返回。

     ------------------------------------------------

    欲在一个MDI程序中有效率的使用多个线程,建议是以一个线程处理所有的用户输入以及用户界面的管理。用其他线程做一些后台的耗时操作。不管怎么做,主线程应该始终有回应。

    线程之间的通讯

    线程通常需要传递数据给另外一个线程,worker线程告诉别人他的工作做完了,GUI线程可以需要交给worker线程一个新工作。PostThreadMessage 类似于PostMessage,不过他的参数之一不是窗口的handle,而是线程ID,当然,接收端必须有消息队列。

    BOOL PostThreadMessage(          
        DWORD idThread,  
    //线程ID,可以有GetCurrentThreadID或CreateThread获得
        UINT Msg,      
        WPARAM wParam,
        LPARAM lParam
    );

    返回值:如果成功的Post出去,返回TRUE。

    以消息作为通讯方式,比起标准技术如全局变量等,有很大好处,比如目标线程很忙碌,则负责post的那个线程不会停滞下来。如果对象是同一进程的线程,可以自定义消息,如WM_APP+0X100等,并配置一块结构,防止你想要传递的数据。然后把结构指针当做lParam,接收端在处理完消息后负责释放内存。

    锁住GDI对象

     GDI对象被每个进程拥有,而被每个线程锁定。如果一个线程正在使用一个GDI对象,该对象将被锁定,其他线程没有办法在使用它。

  • 相关阅读:
    POJ 2348 Euclid's Game【博弈】
    POJ 2484 A Funny Game【博弈】
    HDU 4193 Non-negative Partial Sums【单调队列】
    占坑补题
    Codeforces 658D Bear and Polynomials【数学】
    Codeforces 658C Bear and Forgotten Tree 3【构造】
    Codeforces 658B Bear and Displayed Friends【set】
    POJ 1704 Georgia and Bob【博弈】
    1001. A+B Format

  • 原文地址:https://www.cnblogs.com/kwliu/p/2195905.html
Copyright © 2020-2023  润新知