gpt4 book ai didi

multithreading - 将字符串数据从线程发送到主窗体

转载 作者:行者123 更新时间:2023-12-03 14:45:28 26 4
gpt4 key购买 nike

在Dephi中,我创建了一个线程,像这样,它会不时向主窗体发送消息

Procedure TMyThread.SendLog(I: Integer);
Var
Log: array[0..255] of Char;
Begin
strcopy(@Log,PChar('Log: current stag is ' + IntToStr(I)));
PostMessage(Form1.Handle,WM_UPDATEDATA,Integer(PChar(@Log)),0);
End;

procedure TMyThread.Execute;
var
I: Integer;
begin
for I := 0 to 1024 * 65536 do
begin
if (I mod 65536) == 0 then
begin
SendLog(I);
End;
End;
end;

其中 WM_UPDATEDATA 是自定义消息,定义如下:

const
WM_UPDATEDATA = WM_USER + 100;

在主窗体中,它将执行以下操作来更新列表:

procedure TForm1.WMUpdateData(var msg : TMessage);
begin
List1.Items.Add(PChar(msg.WParam));
end;

但是,由于发送到主窗体的Log字符串是一个局部变量,调用SendLog后该变量就会被销毁。而 TForm1.WMUpdateData 异步处理消息,因此当调用它时,Log 字符串可能已经被销毁。如何解决这个问题?

我想也许我可以在全局系统空间中分配字符串空间,然后将其传递给消息,然后TForm1.WMUpdateData处理消息后,可以销毁全局空间中的字符串空间。这是一个可行的解决方案吗?如何实现这个?

谢谢

最佳答案

除了您发布局部变量这一事实之外,TWinControl.Handle 属性也不是线程安全的。您应该使用 TApplication.Handle 属性,或者使用 AllocateHWnd() 创建您自己的窗口。

您确实需要在堆上动态分配字符串,将该指针发布到主线程,然后在使用完毕后释放内存。

例如:

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;

或者:

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;

关于multithreading - 将字符串数据从线程发送到主窗体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19060027/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com