Send string data from Thread to main form

前端 未结 3 1600
灰色年华
灰色年华 2020-12-29 14:03

In Dephi, I create a thread, like this, which will send message to main form from time to time

Procedure TMyThread.SendLog(I: Integer);
Var
  Log: array[0..2         


        
3条回答
  •  清歌不尽
    2020-12-29 14:35

    In addition to the fact that you are posting a local variable, the TWinControl.Handle property is not thread-safe, either. You should use the TApplication.Handle property instead, or use AllocateHWnd() to create your own window.

    You do need to dynamically allocate the string on the heap, post that pointer to the main thread, and then free the memory when you are done using it.

    For example:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Application.OnMessage := AppMessage;
      // or use a TApplicationEvents component...
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      Application.OnMessage := nil;
    end;
    
    procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
    var
      S: PString;
    begin
      if Msg.Message = WM_UPDATEDATA then
      begin
        S := PString(msg.LParam);
        try
          List1.Items.Add(S^);
        finally
          Dispose(S);
        end;
        Handled := True;
      end;
    end;
    

    procedure TMyThread.SendLog(I: Integer);
    var
      Log: PString;
    begin
      New(Log);
      Log^ := 'Log: current stag is ' + IntToStr(I);
      if not PostMessage(Application.Handle, WM_UPDATEDATA, 0, LPARAM(Log)) then
        Dispose(Log);
    end;
    

    Alternatively:

    var
      hLogWnd: HWND = 0;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      hLogWnd := AllocateHWnd(LogWndProc);
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      if hLogWnd <> 0 then
        DeallocateHWnd(hLogWnd);
    end;
    
    procedure TForm1.LogWndProc(var Message: TMessage);
    var
      S: PString;
    begin
      if Message.Msg = WM_UPDATEDATA then
      begin
        S := PString(msg.LParam);
        try
          List1.Items.Add(S^);
        finally
          Dispose(S);
        end;
      end else
        Message.Result := DefWindowProc(hLogWnd, Message.Msg, Message.WParam, Message.LParam);
    end;
    

    procedure TMyThread.SendLog(I: Integer);
    var
      Log: PString;
    begin
      New(Log);
      Log^ := 'Log: current stag is ' + IntToStr(I);
      if not PostMessage(hLogWnd, WM_UPDATEDATA, 0, LPARAM(Log)) then
        Dispose(Log);
    end;
    

提交回复
热议问题