多线程问题


 1、UI的多线程问题。
(1)UI线程和工作线程
UI线程:当在某线程中使用窗口操作API时,就会为该线程创建一个UI线程。这UI线程负责把队列消息放到对应的消息队列中,该UI线程无法由用户使用。如:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){ ::MessageBox(NULL, "Hellor!", "Hello", MB_OK);}
如果加上“::MessageBox(NULL, "Hellor!", "Hello", MB_OK);”,则该进程有两个线程,如果去掉“::MessageBox(NULL,
"Hellor!", "Hello", MB_OK);”,则该进程只有一个线程。
(2)VC MFC产生的对话框工程最原始的由两个线程组成,一个是WinMain,一个是UI线程。程序员就是在WinMain线程中添加功能的。
(3)UI线程的消息嵌套:由SendMessage发送消息会导致消息嵌套,原因是:当GetMessage捕捉到系统消息后会调用窗口回调函数
,然后在窗口回调函数中调用SendMessage函数,又导致调用窗口回调函数,如果此时有调用SendMessage函数,继续导致调用窗口
回调函数,如此循环...
可见,如果如下使用加锁的代码会产生自嵌套锁,从而导致系统死掉。
FunA(){   a.lock()   ...   a.unlock();
}
FunB()
{   a.lock()      SendMessage To OnMsgA;   a.unlock();
}
OnMsgA()
{   FunA();   }
所以,在进行UI多线程加锁代码访问时,要注意防止嵌套。
(4) 避免UI线程消息嵌套:由PostMessage发送队列消息,由UI线程接受并放到WinMain线程的消息队列中,由WinMain中的
GetMessage去获取该消息。
 
(5)解决一个磁盘扫描的问题。
一个系统有很多线程使用到存储器信息,而且存储器信息随时都可能更改,如插入存储器、拔除存储器。
错误的做法:
1、提供磁盘扫描的函数,把扫描到的信息推到列表中;读存储器信息的线程从该列表中都数据。这会导致在重新扫描列表的过程中,如果扫描未成功,读线程就去读数据,导致数据访问异常。
2、对磁盘扫描函数加锁,对读存储器信息函数加锁,使扫描的和读的不同是进行。
这种做法需得十分小心,如果在读数据准备显示时,调用了SendMessage函数,而SendMessage的消息响应函数又调用的扫描函数,
就会导致锁嵌套而致系统死掉。(很有可能,我就碰到过很多次。)
3、把扫描和读取当作命令发给存储器管理线程,管理线程按照先来先出的原则处理命令。
这种做法不用对数据加锁,但是如果再出来命令时时间过长,就会导致命令队列加长直至系统瘫痪。
正确的做法:
创建一个线程,负责扫描存储器信息,并把存储器信息加锁写到某列表中,扫描动作不用太频繁,除了接收到插入存储器、拔除存
储器事件时需重新扫描外,其他时间线程可以休息。
其他线程,只会加锁从该线程读存储器信息。
因为线程只采用一个资源,这绝对不会产生死锁;同时其他读存储器信息线程在读到信息后,马上解锁,也不会造成自嵌套锁瘫痪。 

(6)Timer问题。

曾经碰到过一个问题,就是在MFC程序中用了几个Timer,这些Timer是由消息WM_TIMER实现,结果发现程序启动缓慢,同时界面操作卡涩。

后来找到原因了,

MFC的所有Timer都是在一个线程里面执行,同时这个线程还包括了所有其他窗口消息的处理,如果在Timer里面做太多事情的话就会导致其他消息无法被处理,这时就会发现程序启动或程序界面操作缓慢。

建议,在MFC TIMER中不要做太多事情,特别是访问IO的操作。如果必须做很多事情,最好创建线程另做线程定时器。
  
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值