关于消息传递字符串?(20分)

  • 主题发起人 主题发起人 南宫吹云
  • 开始时间 开始时间

南宫吹云

Unregistered / Unconfirmed
GUEST, unregistred user!
如何用自定义的消息传递一个字符串?我的sendmessage是在一个线程中发出的,有时候
发送的顺序会错乱,应该如何避免?
我的发送语句如下:
sendmessage(frmmain.handle,wm_cominfo,0,integer(pchar(inttostr(sbbh)+'号设备接收数据出错,请检查线路!')));
问题是当我接收到此消息后如何将传递过来的字符串显示出来?
showmessage(pchar(@msg.LParam)^);只能显示一个字符,why?
 
showmessage(pchar(msg.LParam));
 
//发送消息的过程
procedure SendMsg(Msg:String);
var
DS: TCopyDataStruct;
hd: THandle;
begin
Ds.cbData:=Length(Msg) + 1;
GetMem(Ds.lpData, Ds.cbData );
StrCopy(ds.lpData,PChar(Msg));
Hd:=FindWindow('TFrmMain', Nil); // 获得接受消息窗口的句柄
if Hd <> 0 then // 发送WM_COPYDATA消息
SendMessage(Hd, WM_COPYDATA, Application.Handle,Cardinal(@ds));
FreeMem(Ds.lpData); //释放资源
end;

//在接受消息的窗口添加消息处理
...
public
procedure MyMessage(var t:TWMCopyData);Message WM_COPYDATA;
...

procedure TFrmMain.MyMessage(var t:TWMCopyData);
var s:String;
begin //接受消息并显示。
s:=StrPas(t.CopyDataStruct^.lpData);
ShowMessage(s)
end;
 
哇,一语道破呀,请帮我再看看这个问题:我的sendmessage是在一个线程中发出的,有时候
发送的顺序和接收的顺序会错乱,应该如何避免?
分就全是你的了。
 
如果是SendMessage的话,只能对方处理了消息才返回的,因此不可能出现你说的情况
除非你是多个线程同时用SendMessage发送消息,那就不能保证顺序问题了。除非你采用
线程同步机制,但这样的话跟一个线程也就没什么区别了。
 
还有一点不明白,请教二位:
  程序中可以看出来,发送消息的时候实际上是发送的字符串在内存中的地址,如果发送
多个消息,在内存中发配的空间越来越多,可是在你们的程序中,我没有看到释放这些资源
的代码,这样会不会浪费资源呢?
 
用postmessage();接到消息后马上把这个字符拷贝到一个缓冲里
 
TO xianjun:
是这样的,确实在我的程序中存在两个线程,在第一个线程中创建了第二个线程,第一个线
程是一个循环,循环中创建第二个线程,但是我有语句:
while ... do
begin
...
ieid:=6;
comprocess.Create(sbbh,ot);
while ieid=6 do;
...
next;
...
end;
第二个线程执行完,ieid的值将会在0~5之间,因此第二个线程没有执行完,第一个线程是不
会往下执行的,这样写有什么不对吗?
 
我的主程序中有以下自定义过程,作用是显示一信息提示窗口:
procedure TfrmMain.showfrmsg(s: string);
begin
frminfo.show;
frminfo.Memoinfo.Lines.Add(formatdatetime('yyyy-mm-dd hh:mm:ss:',now));
frminfo.Memoinfo.Lines.Add('------------------------------------');
frminfo.Memoinfo.Lines.Add(s);
frminfo.Memoinfo.Lines.Add('');
end;
当我在线程中直接调用frmmain.showfrmsg的事件时,frminfo上的memoinfo会莫名其妙的
消失,程序仍然在运行,而且退出程序时执行非法操作,错误信息如下:
Exception EWin32Error in module mccq.exe at 0000E5A4.A Win32 API function failed.
所以我只好出此下策,用消息。如果有好的方法能立即显示状态信息,世界将是多么美好啊!
 
string类型是Delphi生存期自管理类型,你用完了就会释放空间的。
线程并不象过程调用,因此不存在说“第二个线程没有执行完,第一个线程是不会往下
执行的” 除非你在第二个线程开始执行前挂起第一个线程,执行完后再Resume。
线程中要更新UI一定要用Synchronize方法
 
const WM_ADDUSERTOLIST =WM_USER +1;
private
procedure DOWM_AddUserToList(var Msg: TWMCopyData);message WM_ADDUSERTOLIST;
...
...

procedure TForm1.DOWM_AddUserToList(var Msg: TWMCopyData);
var
Buffer: String;
begin
Buffer :=StrPas(Msg.CopyDataStruct^.lpData);
ShowMessage(Buffer);
end;
procedure TForm1.MessageSend(const MsgStr: String);
var
cpDataStruct: TCopyDataStruct;
begin
FillChar(cpDataStruct, SizeOf(TCopyDataStruct), Char(0));
cpDataStruct.lpData :=PChar(MsgStr);
SendMessage(AForm.Handle, WM_ADDUSERTOLIST, 0, LParam(@cpDataStruct));
FreeAndNil(@cpDataStruct);
end;
 
TO xianjun:
多谢您的回答,上面所说的ieid为一个全局变量,我说的意思并不是指第一个线程不再执行
了,它也在执行,但它是个做空循环,直到等待第二个线程执行完毕,这两个线程是在并行
运行没错,只要线程一检测到ieid变化了就往下运行。

>>线程中要更新UI一定要用Synchronize方法
这个方法我也用过,可是不能带参数,使用非常不方便,而且如果调用主线程中的这一过
程,主界面就停止响应任何消息了,所以我才把它放在线程里执行,让主界面也能响应用
户的请求。
 
fxWSY, ArJianzeng:
你们的方法确实可行,谢谢你们。

张无忌兄:
用postmessage();接到消息后马上把这个字符拷贝到一个缓冲里
到哪个缓冲?在哪里找到它?postmessage是把消息发送到窗口的消息队列中了,与此窗口
中其它的消息排队,这样不能立即显示状态信息。
 
第一个线程能把它自己挂起吗?
 
发送一个消息让他等待,然后等另一个进程完成后在唤醒这个进程。。。
 
那么我的这种做法不行吗?用全局变量,当变量改变后继续往下执行,否则等待。
 
你能不能这么做,就是把要处理的某个数据先保存在一个文件里,然后发送消息给某个进程,
这个消息的参数就是数据所在的文件名,然后你可以使用这个进程读取这个文件里的数据,
只要文件名不重复就可以了。
 
TO ArJianzeng:
  由于这个程序的特殊性,不能这么做,您先听我把整个过程说一下:
我做的是一个串口通讯程序,一共有10台设备,我的第一个线程(名为oncecom)循环发送
命令,查询设备有没有请求。当查询第一台设备时,如果设备有请求,返回请求,我处理
后再返回处理结果,设备返回接收数据成功或错误(提示)。这是一个完整的通讯过程。
>>发送一个消息让他等待,然后等另一个进程完成后在唤醒这个进程。。。
问题是:唤醒这个进程后,这个进程是从头开始执行的。
我需要的是这样:
 while not 设备表.eof do
begin
发送命令
...
等待设备返回
...
    如果校验没错 
    创建线程2 (处理返回后的数据)
    这时,线程一应该停止或等待线程2的完成
    线程2完成后线程一继续往下执行
...
    下一个设备
  end;
如何将这两个线程配合工作是现在最头疼的问题。你说发送消息,让线程一响应,可是却
不能在线程2执行完处继续往下执行。
 
其实也就是两个线程同步的问题吧:
一个线程负责发送消息,一个线程负责接收消息,只不过是在接收线程接收到设备的返回
信息以前不能继续发送下一个消息。
呵呵,如果真的是这样的话,为什么要两个线程呢? 因为你自始致终都只有一个线程在执行
 while not 设备表.eof do
begin
发送命令
...
等待设备返回
...
    如果校验没错 
调用处理过程处理返回后的数据,这里你为什么要用另一个线程来做呢? 用这个
线程本身也是一样的,因为现在它是没事可做了。
...
    下一个设备
  end;
 
如果你是因为要让主界面能响应用户操作的话,你就应该把整个处理过程放在
一个独立的线程中,这样才有效果。 如果用你上面说的,主界面还是无法响应你的消息的。
 
后退
顶部