PostThreadMessage在线程中应用(以多线程网站数据采集为例)

本文详细介绍了如何在Delphi中使用线程进行数据采集并实现与主线程的高效通信,通过模拟窗口消息处理技术优化用户体验。主要内容包括线程基本操作、消息驱动机制、错误处理策略以及中断控制,旨在提高软件模块的并发处理能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

转载于:https://www.cnblogs.com/lwm8246/archive/2011/10/06/2199994.html

Creating Windows CreateMDIWindow CreateWindow CreateWindowEx RegisterClass RegisterClassEx UnregisterClass Message Processing BroadcastSystemMessage CallNextHookEx CallWindowProc DefFrameProc DefMDIChildProc DefWindowProc DispatchMessage GetMessage GetMessageExtraInfo GetMessagePos GetMessageTime GetQueueStatus InSendMessage PeekMessage PostMessage PostQuitMessage PostThreadMessage RegisterWindowMessage ReplyMessage SendMessage SendMessageCallback SendMessageTimeout SendNotifyMessage SetMessageExtraInfo SetWindowsHookEx TranslateMessage UnhookWindowsHookEx WaitMessage Window Information AnyPopup ChildWindowFromPoint ChildWindowFromPointEx EnableWindow EnumChildWindows EnumPropsEx EnumThreadWindows EnumWindows FindWindow FindWindowEx GetClassInfoEx GetClassLong GetClassName GetClientRect GetDesktopWindow GetFocus GetForegroundWindow GetNextWindow GetParent GetProp GetTopWindow GetWindow GetWindowLong GetWindowRect GetWindowText GetWindowTextLength IsChild IsIconic IsWindow IsWindowEnabled IsWindowUnicode IsWindowVisible IsZoomed RemoveProp SetActiveWindow SetClassLong SetFocus SetForegroundWindow SetParent SetProp SetWindowLong SetWindowText WindowFromPoint Processes and Threads CreateEvent CreateMutex CreateProcess CreateSemaphore CreateThread DeleteCriticalSection DuplicateHandle EnterCriticalSection ExitProcess ExitThread GetCurrentProcess GetCurrentProcessId GetCurrentThread GetCurrentThreadId GetExitCodeProcess GetExitCodeThread GetPriorityClass GetThreadPriority GetWindowThreadProcessId InitializeCriticalSection InterlockedDecrement InterlockedExchange InterlockedIncrement LeaveCriticalSection OpenEvent OpenMutex OpenProcess OpenSemaphore PulseEvent ReleaseMutex ReleaseSemaphore ResetEvent ResumeThread SetEvent SetPr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值