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 消息映射框架

  • 相关阅读:
    [HAOI2015]按位或——Min-Max容斥+FWT
    HDU 4773 Problem of Apollonius——圆反演
    类欧几里得小结
    线性规划(单纯形法)知识整理
    奇怪的数学题(51nod1847)——min_25筛+杜教筛+第二类斯特林数
    CSP-S 2019 游记
    2019.11.11~2019.11.12考试总结
    2019.11.6~2019.11.7考试总结
    1019.11.1~2019.11.2考试总结
    Final-阶段站立会议4
  • 原文地址:https://www.cnblogs.com/Esperanto/p/3227478.html
Copyright © 2011-2022 走看看