Multithreading 后消息LPRAM截断

Multithreading 后消息LPRAM截断,multithreading,delphi,delphi-7,postmessage,Multithreading,Delphi,Delphi 7,Postmessage,我的应用程序有一个工作线程,我使用PostMessage向主线程发送一个字符串。对于1条消息,字符串在到达主线程中的消息处理程序时被截断 该字符串在工作线程中由如下原始数据字符串构造。它在最后的“20”结束 “0101000000003000010200000885008855343414E20454447452000000000000000000000000000000000000000000000000” 解码为我要发送的字符串,如下所示,这是正确的: '0100.50000 LSB0288

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

该字符串在工作线程中由如下原始数据字符串构造。它在最后的“20”结束

“0101000000003000010200000885008855343414E20454447452000000000000000000000000000000000000000000000000”

解码为我要发送的字符串,如下所示,这是正确的:

'0100.50000 LSB0288.588.5扫描边缘'

创建“扫描边缘”部分并将其发布的代码是: 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.50000 LSB0288.588.5扫描EDG'0


如何更正此问题?

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

您需要:

1使用SendMessage而不是PostMessage,以便字符串在消息处理程序退出之前保持在作用域中:

SendMessage(MainHandle, UM_CLONE, UM_756, LPARAM(PChar(s_out)));
2在内存中动态分配一个字符串,根据需要填充它,发布它,然后在完成复制后让主消息处理程序释放它:

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);


注意,我还将整数转换更改为LPRAM。如果您升级到Delphi XE2或更高版本,这一点非常重要。PostMessage和SendMessage使用LPRAM,而不是整数。您可以在Delphi7中使用它,因为LPARAM在该版本中是Integer的别名,但在现代Delphi版本中不再是这种情况。LPARAM现在是NativeUInt的别名。LPARAM在Win32 API中一直是一种非单一类型,Delphi在早期版本中只是弄错了,但自从添加了对64位和跨平台开发的支持之后,Embarcadero一直在推动RTL/VCL中的类型正确性。如果没有正确匹配正确的数据类型,则可能会在运行时导致范围检查错误等。

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

您需要:

1使用SendMessage而不是PostMessage,以便字符串在消息处理程序退出之前保持在作用域中:

SendMessage(MainHandle, UM_CLONE, UM_756, LPARAM(PChar(s_out)));
2在内存中动态分配一个字符串,根据需要填充它,发布它,然后在完成复制后让主消息处理程序释放它:

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);


注意,我还将整数转换更改为LPRAM。如果您升级到Delphi XE2或更高版本,这一点非常重要。PostMessage和SendMessage使用LPRAM,而不是整数。您可以在Delphi7中使用它,因为LPARAM在该版本中是Integer的别名,但在现代Delphi版本中不再是这种情况。LPARAM现在是NativeUInt的别名。LPARAM在Win32 API中一直是一种非单一类型,Delphi在早期版本中只是弄错了,但自从添加了对64位和跨平台开发的支持之后,Embarcadero一直在推动RTL/VCL中的类型正确性。如果没有正确匹配正确的数据类型,则可能会在运行时导致范围检查错误等。

它将仅在同一进程中工作。对于使用消息的进程间通信,请使用WM_COPY,它将按预期整理内容。您考虑的是WM_COPYDATA。它将仅在同一进程内工作。对于使用消息的进程间通信,请使用WM_COPY,它将按预期整理内容。您考虑的是WM_COPYDATA。