全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4376
推到 Plurk!
推到 Facebook!

由主form sendmessage 到thread 為何會收不到任何message

尚未結案
danielx2000
一般會員


發表:29
回覆:33
積分:22
註冊:2002-09-02

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-10-20 11:19:14 IP:59.120.xxx.xxx 未訂閱
請問各位: 我想要做一個實驗, 由主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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-11-11 14:39:42 IP:218.175.xxx.xxx 未訂閱
有人遇過同樣的message 問題嗎?請幫我解答 感謝
One2Free
一般會員


發表:26
回覆:28
積分:20
註冊:2004-05-12

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-11-12 22:22:40 IP:219.135.xxx.xxx 未訂閱
线程中没有消息循环机制,你可以自己去加. 贴个文章你看看, 忘了出处了:  
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(tID
0)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;
 
系統時間:2024-05-17 10:30:14
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!