QWorker更新-在Win32平台上枚举作业状态加上堆栈显示

在多线程编程中,死锁是一个绕不过去的话题,一旦发生死锁,要想知道程序死在那儿,为啥死的,是一个艰难的选择。QWorker为用户新提供的EnumWorkerStatus函数,可以轻松的报告每个工作者的状态、正在处理的作业、及工作者处理作业的堆栈调用情况,通过跟踪这些信息,大家可以方便的抓取到每个工作者当前在干什么,从而可以确定出系统中的作业是那个线程相互阻塞造成问题发生。

要使用本功能,必需让编译器生成Map文件,以便程序知道指定的地址对应的是啥函数及源码信息。关于这方面的信息,请参考文章:Delphi/C++ Builder Map文件格式解析

在程序运行过程中,你可以随时调用EnumWorkerStatus来枚举每个工作者的状态。当指定的工作者不空闲时,就会列出相应的工作者的调用堆栈,如下代码:

运行结果如下:

EnumWorkerStatus

我们可以看到,线程23当前正处于忙碌中,执行的作业是main单元的TForm1.DoLongTimeWork函数,其它的工作者处于空闲状态。

我们再结合EnumWaitChains函数,就可以很方便跟踪出死锁的状态。

【注意】

EnumWaitChain是调用Windows的API,所以受Windows版本限制,运行在Windows Vista或Windows Server 2008以上时,会支持该功能。

看下在的代码:

运行效果:

WaitChains

看上面的结果中的线程7176的状态:

这说明线程7176和线程8988都在使用同一个临界,那么我只需要再结合各个线程的堆栈信息,就可以定位到出错的行。

看堆栈跟踪效果:

debugstacks

好吧,从上面看,我们锁冲突分别位于线程8644的第77行函数TForm4.Button3Click和线程7464的第System.SyncObjs.pas中的第1023行试图进入临界,这样一清二楚,然后接下来的事情就是去修改代码,保证它们不冲突就好了。

分享到:

0 条评论

沙发空缺中,还不快抢~