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

转载于:https://www.cnblogs.com/Esperanto/p/3227478.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值