PostThreadMessage 顾名思议,向线程中发送消息.下面讲讲我在线程中的应用体会 在Delphi 中,我们大多数人,使用线程的时候,都会用到系统自带的TThread 类,来完成线程的操作。 从TThread 中派生出一个自己的类,然后重载 Execute 函数,其在TThread中被定义成了抽象类(纯虚类C++)。 子类必须重载这个函数.在此函数中,写入你要完成的任务代码. 例如 最简单应用 TCustXXXXThread=class(TThread) public procedure Execute();override; end; TCustXXXXThread.Execute() begin while (not Terminated) do begin //do something end; //退出后,线程结束 end; 一个线程要完成一项(多项)任务,就涉及到一个最基本也是不可回避的问题,怎样与线程进行通信,把输入参数传递给线程 把线程的运行结果,取出来。实现的方法很多,今天这里重点介绍下。 我的一个软件模块中,需要做数据采集, 把某网站上的数据采集下来。然后,分解提取出需要的数据,整理后,存入数据库 以便于后续处理。网络通信采用了 Indy控件,负责下载网页文本。由于数据量比较大,网站的数据是分页的。我这里也要循环 读取每个网页的文本。数据下载,分解都是耗时操作。很自然的就需要把它们放入线程中运行。以保证主界面不被卡死。 实现的伪代码 while(ture) do begin (1)采集网站文本,通知主线程数据下载完毕 (2)分解网站文本,提取数据, while(ture) do begin 提取数据记录,发消息给主线程(记录N)分解完毕。 end; if 采集的网站数据的最后一页 then 退出. end; 我们开发软件的时候,常常提到系统架构。那么这个模块的架构应该如何那。 1)主要的处理函数全部在线程中运行 2)中间的运行结果要通知主线程,用于界面更新 3)网络程序,必须要考虑到错误处理问题。例如,网站链接超时。 4) 接受主线程命令随时中断采集. 根据此种情况及个人喜好原因。决定采用模拟窗口消息处理的方式,作程序的主框架。以消息的读取,转换,分发 为主线。 代码框架如下: TWebSample=class(TThread) private //.......... protected procedure WndProc(var AMsg:TMessage); //模拟窗口消息处理 procedure Execute();override; //线程运行的主函数 public MainWndHande:THandle; //主窗口句柄,用于发消息给主窗口用 end; TWebSample.Execute() var _Msg:tagMsg; AMessage:TMessage; begin //模拟消息驱动, //在这里起到一个消息泵的作用,用于消息的接受,分析,转发 while (not Terminated) do begin if PeekMessage(_Msg,0,WM_USER,WM_USER + 1100,PM_REMOVE) then begin AMessage.Msg := _Msg.message; AMessage.WParam := _Msg.wParam; AMessage.LParam := _Msg.lParam; AMessage.Result := 1; WndProc(AMessage); //消息的转发 if AMessage.Result = 0 then Break; //退出线程 end else Sleep(1); //避免没有消息进来的时候,CPU 占用率过高.具体数值,可以实验测定。 end; end; procedure TWebSample.WndProc(var AMsg:TMessage); //模拟窗口消息处理 begin if AMsg.Msg = MSG_XXXX_01 then begin //消息处理 //发消息给主窗体,用于数据更新等操作 SendMesesage(MainWndHand,MSG_MAIN_XXXX,wParam,lParam); end else if AMsg.Msg = MSG_XXX_02 then begin //消息处理 end; end; //线程介绍完了,下面要谈谈主窗体怎样发消息(命令)给线程的伪代码 procedure TfrmSaleAnaly.btnGoClick(Sender: TObject); var ThreadObj: TWebSamplebj; begin ThreadObj := TWebSamplebj.Create(TRUE); ThredObj 对象的初始化 ThredObj.Resume(); //启动线程运行 //发出控制命令给线程 PostThreadMessage(ThreadObj.ThreadID, MSG_XXXX_01, wParam, lParam); end; 如果投递消息到线程中,没有反应,可以试试下面的方法 procedure PostThreadMessageEh(ThreadID:DWORD;Msg:DWORD;WParam,LParam:Integer); begin while(not PostThreadMessage(ThreadID,Msg,WParam,LParam)) do Sleep(5); end; MSDN 关于此问题的解决办法. The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use one of the following methods to handle this situation: Call PostThreadMessage. If it fails, call the Sleep function and call PostThreadMessage again. Repeat until PostThreadMessage succeeds.

浙公网安备 33010602011771号