由主form sendmessage 到thread 為何會收不到任何message |
尚未結案
|
danielx2000
一般會員 發表:29 回覆:33 積分:22 註冊:2002-09-02 發送簡訊給我 |
請問各位:
我想要做一個實驗,
由主FORM 啟動後,會create 5 個function 相同但各自獨立的thread,
每個thread 都各有一個編號 從0..4,
每一個thread 會先等待上一個thread 丟message 過來,然後傳遞給下一個thread,如此循環直到結束. (執行時,由主FORM 先trigger thread0) 我現在遇到的問題是,
當我由主form trigger thread0時, thread 都收不到任何message,
但是若由thread sendmessage 到form 卻可以收的到資料,
我用的是 WM_COPYDATA 傳遞一個 structure , Thread_key = msg = 'KEY' 不知道是哪裡出問題,
請各位幫忙解答
Thanks
主form : main.pas procedure TMainForm.btnStartClick(Sender: TObject); var R: Trec; P: COPYDATASTRUCT; dc: THandle; s: string; ret:longBool; begin R.msg := Thread_key ; dc := Thread[0].handle ; try if dc <> 0 then begin P.dwData := dc; P.cbData := Sizeof(R); P.lpData := @R; repeat ret:= PostThreadMessage(dc, WM_COPYDATA, dc, Integer(@P)); sleep(2); until ret=false ; end; except end; end; ================================================================= Threadutil.pas type Trec = record index: integer; // Thread index msg: string; end; procedure WMCopy(var Msg: TMessage); message WM_COPYDATA; procedure fileUtil.WMCopy(var Msg: TMessage); var R: Trec; P: COPYDATASTRUCT; id: integer; dc: THandle; begin try P := COPYDATASTRUCT(Pointer(Msg.lParam)^); R := TRec(P.lpData^); sleep(10); if ( R.msg = Thread_key ) then begin if R.index >= 0 then begin R.index := (R.index 1) mod iniCount; dc := thread_handle[R.index]; if dc <> 0 then begin P.dwData := dc; P.cbData := Sizeof(R); P.lpData := @R; PostThreadMessage(dc, WM_COPYDATA, dc, Integer(@P)); sleep(10); end; end; end; except // end; end; |
danielx2000
一般會員 發表:29 回覆:33 積分:22 註冊:2002-09-02 發送簡訊給我 |
|
One2Free
一般會員 發表:26 回覆:28 積分:20 註冊:2004-05-12 發送簡訊給我 |
线程中没有消息循环机制,你可以自己去加.
贴个文章你看看, 忘了出处了:
Delphi关于线程的消息处理 在平时写程序时,总是碰到窗体(TForm)与线程(TThread)消息通信问题。令人烦恼的是窗体不能向线程(TThread)发送消息(线程没有窗口句柄)。经过几天的折腾,想出二种解决方案,拿出来跟大家探讨探讨。 第一。我们知道VC 中的MFC类库是自已封装了消息处理(BEGINMESSAGE,ENDMESSAGE),在MFC中对消息的处理是通过建立一张消息映射表,而把方法(function)或过程(procedure)的地址保存到映射表里(消息处理实质上是方法或过程的调用),再加上一个消息分发机制,来实现消息的接收发送<详见VC 技术内幕>。所以我们只要为线程里建立一张消息映射表,并建立相应的消息分发机制。这样就可以处理窗体发送到线程的消息。以下代码是实现消息映射表和消息分发的类(详见<..\消息处理设计(线程)1\MessageHandle.pas>中) unitMessageHandle; interface usesmessages,Classes,SysUtils,Dialogs; constPMSG_BASE=$BE00;//自定义消息基址; PMSG_NUM=200;//消息表大小; {**自定义消息处理类 *;功能=建立自定义消息表,处理线程之间 *以及与主窗体之间的自定义消息(宏观) *} //消息处理句柄 TMessageHandle=procedure(varMessage:TMessage)ofObject; TPDispatcher=class(TObject) private //消息对应表(消息ID为数组下标); MessageHandles:arrayofTMessageHandle; //从消息ID得到数组ID functionGetIndexFromMsgID(constaMessageID:cardinal):Integer; public constructorCreate; destructorDestroy; //发送消息 procedureSendMessage(varMessage:TMessage);overload; //添加自定义消息到消息对应表; procedureAddHandle(constaMessageID:cardinal;aMessageHandle:TMessageHandle); end; // implementation {TPDispatcher} constructorTPDispatcher.Create; vari:Integer; begin SetLength(MessageHandles,PMSG_NUM);//200个消息的消息对应表 //初始化消息队列; fori:=0toPred(PMSG_NUM)do MessageHandles[i]:=nil; end; destructorTPDispatcher.Destroy; begin {释放消息对应表} FreeAndNil(MessageHandles); end; procedureTPDispatcher.AddHandle(constaMessageID:cardinal; aMessageHandle:TMessageHandle); vartID:Integer; begin tID:=GetIndexFromMsgID(aMessageID); Assert((tID>0)or(tID0)or(tID: Unitunit1 const {自定久线程消息} MY_MESSAGE2=PMSG_BASE 02; type TForm1=class(TForm) AddMsgList:TButton; SendThead:TButton; sendForm:TButton; sendOther:TButton; procedureSendTheadClick(Sender:TObject);//发送消息 procedureFormCreate(Sender:TObject); procedureFormDestroy(Sender:TObject); private Fdispatcher:TPDispatcher;消息映射表类 Fhandle:TPHandler; FThread:TPTHread;自定义线程类 public {Publicdeclarations} end; var Form1:TForm1; implementation {$R*.dfm} procedureTForm1.SendTheadClick(Sender:TObject); varaMessage:TMessage;begin aMessage.Msg:=MY_MESSAGE2; aMessage.WParam:=1; Fdispatcher.SendMessage(aMessage); end; end; procedureTForm1.FormCreate(Sender:TObject); begin {创建消息映射表类} Fdispatcher:=TPDispatcher.Create; Fhandle:=TPHandler.Create; {创建线程} FThread:=TPThread.Create(false); {向映射表中增加消息} Fdispatcher.AddHandle(MY_MESSAGE2,FThread.DoMessage); end; procedureTForm1.FormDestroy(Sender:TObject); vari:Integer; begin FreeAndNil(Fdispatcher); FreeAndNil(Fhandle); fori:=0to3do FreeAndNil(FThread[i]); end; 第二。窗口可以处理消息是因为它有窗口句柄。为了使线程也能处理消息,我们可以通过为线程加上一个相应窗口类的窗口名柄。(源码在<..\消息处理设计(线程)2\pThread.pas>中) unitpThread; interface usesclasses,sysutils,Windows,Messages,Dialogs; constMY_MESSAGE1=$BD00 01; Type {**消息处理线程类 *;功能=添加线程处理消息能力, *} TPMsgThread=class(TThread) private //窗口句柄 FWndHandle:HWND; //窗口数据信息 FWndClass:WNDCLASS; //指向窗口回调函数的指针 FObjectInstance:Pointer; //初始化窗口数据 procedureInitWnd; //创建隐藏窗口 procedureCreateWnd; //注册隐藏窗口 procedureRegistWnd; procedureDestroyWnd; //窗口回调函数 procedurepWndProc(varMessage:TMessage);virtual; protected procedureExecute;override; procedureDoTerminate;override; public constructorCreate(CreateSuspended:Boolean);virtual; propertyWndHandle:HWNDreadFWndHandlewriteFWndHandle; end; implementation constWND_NAME='PY20'; {TPMsgThread} constructorTPMsgThread.Create(CreateSuspended:Boolean); begin inheritedCreate(CreateSuspended); FWndHandle:=Integer(nil); InitWnd; RegistWnd; CreateWnd; end; procedureTPMsgThread.CreateWnd; begin if(WndHandle=Integer(nil))then WndHandle:=CreateWindow(FWndClass.lpszClassName,FWndClass.lpszClassName, WS_POPUPorWS_CAPTIONorWS_CLIPSIBLINGSorWS_SYSMENU orWS_MINIMIZEBOX, GetSystemMetrics(SM_CXSCREEN)div2, GetSystemMetrics(SM_CYSCREEN)div2, 0,0,0,0,FWndClass.hInstance,nil); //置换窗口回调函数 SetWindowLong(WndHandle,GWL_WNDPROC,Longint(FObjectInstance)); end; procedureTPMsgThread.DestroyWnd; begin UnregisterClass(FWndClass.lpszClassName,FWndClass.hInstance); DestroyWindow(WndHandle); end; procedureTPMsgThread.DoTerminate; begin inherited; DestroyWnd; end; procedureTPMsgThread.Execute; begin end; procedureTPMsgThread.InitWnd; begin FwndClass.lpszClassName:=PChar(WND_NAME); FWndClass.hInstance:=Handle; FWndClass.lpfnWndProc:=@DefWindowProc; end; procedureTPMsgThread.pWndProc(varMessage:TMessage); begin end; procedureTPMsgThread.RegistWnd; begin FObjectInstance:=Classes.MakeObjectInstance(pWndProc); if(FWndClass.hInstance<>Integer(nil))then RegisterClass(FWndClass); end; |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |