zoukankan      html  css  js  c++  java
  • SetwindowText 之线程阻塞

    示意代码:

    CriticalSection g_Section;
    CDialog g_Dlg;

    // 工作线程函数
    UINT TreadFunc_A(PVOID para)
    {
    Sleep(10);

    g_Section.Lock();

    Sleep(3000);
    g_Dlg.m_Show_Edit.SetWindowText("TreadFuncA");
    // Beep(400,20);

    g_Section.Unlock();
    }

    // 窗口按钮消息函数
    void CDialog::OnButton1()
    {
    g_Section.Lock();

    g_Dlg.m_Show_Edit.SetWindowText("OnButton1");
    // Beep(800,20);
    g_Section.Unlock();
    }

    死锁出现条件:
    TreadFunc_A 进入 g_Section.Lock() 临界区
    在没有释放临界锁之前OnButton1()触发,g_Section.Lock() 阻塞等待
    ....永远都等不到了!

    实验:
    如果把g_Dlg.m_Show_Edit.SetWindowText替换成Beep,测滴答滴答的运行OK,不会出现死锁。
    看来问题出在SetWindowText上了。

    分析:
    导致死锁的一个隐含机制:SetWindowText 的实现使用了 SendMessage(WM_SETTEXT,...)
    而SendMessage是阻塞调用,等待窗口处理函数完成才返回。同时OnButton1也是窗口消息处理函数的回调映射,
    所以 g_Dlg.m_Show_Edit.SetWindowText("TreadFuncA"),在等待窗口消息处理函数的返回,线程被阻塞。
    而OnButton1占用了窗口消息函数执行,申请临界锁被阻塞。这样工作线程TreadFunc_A 占用临界锁同时等
    待窗口消息处理函数的返回,而界面线程占用窗口消息处理函数同时等待临界锁,于是就永远死翘翘的等下去了。

    结束语:
    MFC下面厚厚的封装,鬼才知道是什么实现机制。为了吃块糖,只需要剥开糖纸即可,为什么还要了解糖的加工工艺。
    吃别人的东西,直管往嘴里放就得了,出了问题再想办法,也只能这么着了。

    扩展阅读:

    1)Windows 窗口消息原理 

    2)SendMessage的实现机制

    3)MFC 消息映射框架

  • 相关阅读:
    GoLang设计模式15 策略模式
    GoLang设计模式18 适配器模式
    GoLang设计模式14 状态模式
    GoLang设计模式12 空对象模式
    GoLang设计模式19 桥接模式
    GoLang设计模式17 访客模式
    GoLang设计模式13 观察者模式
    GoLang设计模式16 模板方法模式
    Papervision3D材质
    Papervision3D基本原理
  • 原文地址:https://www.cnblogs.com/Esperanto/p/3227478.html
Copyright © 2011-2022 走看看