Postmessage LParam截断

时间:2012-03-29 19:30:29

标签: multithreading delphi delphi-7 postmessage

我的应用程序有一个工作线程,我使用PostMessage将字符串发送到主线程。对于1条消息,当字符串到达​​主线程中的消息处理程序时,该字符串将被截断。

字符串在工作线程中由一串原始数据构成,如下所示。它在最后的'20'结束。

'01010000000030000102000008850008855343414E204544474520000000000000000000'

解码为我要发送的字符串,看起来像这样,这是正确的:

'0100 0.50000 LSB0288.588.5SCAN EDGE'

创建“SCAN EDGE”部分并发布它的代码是: tmp和s_out是字符串

x := 35;
for i := 1 to 10 do
begin
  tmp := '$' + copy(s,x,2);
  TryStrToInt(tmp,dec);
  s_out := s_out + chr(dec);
  x := x + 2;
end;
PostMessage(MainHandle,UM_CLONE, UM_756, Integer(PChar(s_out)));

主线程中的消息处理程序是: 我是一个字符串

i := pChar(msg.LParam);

当它到达主线程时,我在调试器中看起来像这样:

'0100 0.50000 LSB0288.588.5SCAN EDG'#0

我该如何纠正?

1 个答案:

答案 0 :(得分:12)

您正在发布String变量的内容,该变量是调用PostMessage()的线程过程的本地变量。如果String超出范围并在主线程处理发布的消息之前被释放,则内存将是垃圾。

您需要:

1)使用SendMessage()代替PostMessage(),以便String保留在范围内,直到消息处理程序退出:

SendMessage(MainHandle, UM_CLONE, UM_756, LPARAM(PChar(s_out)));

2)在内存中动态分配String,根据需要填充它,发布它,然后让主消息处理程序在复制它时释放它:

var
  s_out: PString;

New(s_out);
...
s_out^ := s_out^ + chr(dec);
...
if not PostMessage(MainHandle, UM_CLONE, UM_756, LPARAM(s_out)) then
  Dispose(s_out);

var
  ps: PString;
  i: String;

ps := PString(msg.LParam);
i := ps^;
Dispose(ps);

PS:注意我也将您的Integer()广告变为LPARAM()。如果您升级到Delphi XE2或更高版本,这一点非常重要。 PostMessage()SendMessage()使用LPARAM,而不是Integer。您可以在Delphi 7中使用它,因为LPARAM是该版本中Integer的别名,但在现代Delphi版本中不再是这种情况。 LPARAM现在是NativeUInt的别名。 LPARAM一直是Win32 API中的一个非类型类型,Delphi在早期版本中出错了,但是Embarcadero实际上一直在推动RTL / VCL中的类型正确性,因为它增加了对64位和交叉的支持 - 平台开发。如果未正确匹配正确的数据类型,则可能会在运行时导致范围检查错误等。