Delphi多线程及消息发送传递结构体参数
2012-01-18 23:36
393 查看
1、Unit2:
2 form 调用 Unit1
PS:好久没搞Delphi了,整个多线程都翻了好多帖子和记忆.
unit Unit2; interface uses windows,classes,NMICMP,SysUtils,StdCtrls,messages; const WM_MY_PING = WM_USER +1024; type //要传递的消息记录. TPingMsg = record msg : array[0..1023] of char; id : integer; Handled : boolean; msg2 : string; //建议如果需要动态管理,比如采用List,采用字符数组的方式会比较好, //因为在动态使用结构时,如过没有处理好,采用string就可能会造成内存泄露. //当然在这里例子中没关系. end; pPingMsg = ^TPingMsg;//定义结构体指针. OnPinging = procedure(Context: integer;Msg : string) of object; ThreadEnd = procedure(Context: integer;Msg:string) of object; TMyPingThread = class(TThread) private FPingEvent : OnPinging; FEndEvent : ThreadEnd; FMsg : string; FSequenceID : integer; FWinHandl : Hwnd; procedure OnPing(Sender: TObject; Host: String; Size, Time: Integer); procedure HandlingEnd; procedure HandlingPing; protected procedure Execute;override; procedure DoTerminate;override; public //采用函数指针的方式,因为传递过来如果是UI控件类的方法,该方法需要访问UI元素,则需要做同步处理, //否则可能会导致错误. constructor Create(WinHandl : Hwnd; SequenceID : integer;OutPut: OnPinging;EndEvent: ThreadEnd);overload; end; implementation { TMyPingThread } constructor TMyPingThread.Create(WinHandl : Hwnd;SequenceID : integer;OutPut: OnPinging; EndEvent: ThreadEnd); begin self.FPingEvent := OutPut; self.FEndEvent := EndEvent; FSequenceID := SequenceID; FWinHandl := WinHandl; inherited Create(true); end; procedure TMyPingThread.DoTerminate; begin inherited; Synchronize(HandlingEnd); end; procedure TMyPingThread.HandlingEnd(); begin if Assigned(self.FEndEvent) then self.FEndEvent(FSequenceID,FMsg); end; procedure TMyPingThread.HandlingPing(); begin if assigned(self.FPingEvent) then FPingEvent(FSequenceID,FMsg); end; procedure TMyPingThread.Execute; var PingObj : TNMPing; begin self.FreeOnTerminate := true; PingObj := TNMPing.Create(nil); PingObj.OnPing := OnPing; try PingObj.Pings := 30; PingObj.Host := 'www.sohu.com'; PingObj.Ping; finally PingObj.Free; end; end; procedure TMyPingThread.OnPing(Sender: TObject; Host: String; Size, Time: Integer); var pMsg : pPingMsg; Msg : TPingMsg; begin //不能直接定义结构体,因为是局部变量,如果是PostMessage,不会等待,会释放的. //但如果采用如下的new方式,程序不会主动释放内存,需要配合Dispose方法用. new(pmsg); //这种情况下,消息接收方不一定能获取到正确的值. FMsg := host+':'+ inttostr(size)+':'+inttostr(Time); strcopy(@(pmsg.msg),pchar(FMsg)); pmsg.id := self.FSequenceID; pmsg.Handled := false; pmsg.msg2 := FMsg+'xxx';//注意,这里增加字符,并不能增加sizeof(pmsg^) Msg.msg2 := FMsg+'xxxx';//注意,这里增加字符,并不能增加sizeof(Msg) strcopy(@(Msg.msg),pchar(FMsg)); //postmessage(FWinHandl,WM_MY_PING, self.FSequenceID,LPARAM(@Msg)); //因此我觉得采用SendMessage比较好,这样内存的释放可以在这里进行,不会造成内存泄露. Sendmessage(FWinHandl,WM_MY_PING, self.FSequenceID,LPARAM(@Msg)); //这种方法是让线程等待消息处理,实际上等效于SendMessage方法调用. {while (pmsg.Handled=false) do begin sleep(10); end; } //采用等待方法则在这里释放空间。如果采用消息接收方处理,则这里不需要释放。 Dispose(Pmsg); //Synchronize(HandlingPing); end; end.
2 form 调用 Unit1
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,Unit2, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Memo2: TMemo; Memo3: TMemo; Memo4: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } FThreadCount : integer; procedure HandlingPing(Context:integer;Msg : string); procedure HanglingEnd(Context:integer;Msg : string); procedure OutPut(Context:integer;Msg : string); procedure PingMsgHdl(var Msg:TMessage);message WM_MY_PING; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var AThread : TMyPingThread; begin FThreadCount := 4; AThread := TMyPingThread.Create(self.Handle, 1,HandlingPing,HanglingEnd); AThread.Resume; AThread := TMyPingThread.Create(self.Handle,2,HandlingPing,HanglingEnd); AThread.Resume; AThread := TMyPingThread.Create(self.Handle,3,HandlingPing,HanglingEnd); AThread.Resume; AThread := TMyPingThread.Create(self.Handle,4,HandlingPing,HanglingEnd); AThread.Resume; end; procedure TForm1.HandlingPing(Context:integer;Msg: string); begin OutPut(Context,Msg); end; procedure TForm1.HanglingEnd(Context:integer;Msg: string); begin OutPut(Context,Msg); FThreadCount := FThreadCount -1; OutPut(1,inttostr(FThreadCount)); end; procedure TForm1.OutPut(Context: integer; Msg: string); begin case context of 1: memo1.Lines.Append(Msg); 2: memo2.Lines.Append(Msg); 3: memo3.Lines.Append(Msg); 4: memo4.Lines.Append(Msg); end; end; procedure TForm1.PingMsgHdl(var Msg:TMessage); var pMsg : pPingMsg; begin pMsg := pPingMsg(Msg.LParam); OutPut(Msg.WParam, pmsg.msg2+'=>'+inttostr(sizeof(pmsg^))); //这个用于等待线程,这里已经处理完毕。当然这只是一种方法. pMsg.Handled := true; //另外一种方法是在这里释放内存,但用户又可能会忘记释放。 //dispose(pMsg); end; end.
PS:好久没搞Delphi了,整个多线程都翻了好多帖子和记忆.
相关文章推荐
- Delphi多线程及消息发送传递结构体参数
- 关于Delphi中多线程传递参数的简单问题
- Win32 API 多线程编程——一个简单实例(含消息参数传递)
- unity中利用sentmessage发送消息传递多个参数
- delphi发送焦点移动消息的函数及参数
- 多线程中MFC对象参数的传递
- 多线程传递参数
- 多线程:如何在调用线程时传递参数 --转
- Delphi中多线程用消息实现VCL数据同步显示
- Delphi动态事件深入分析(对象方法在调用的时候会传递一个隐含的Self指针,而该指针的值在EAX中。即左边第一个参数)
- 【转】 多线程 传递参数
- C# 给多线程传递参数的三种方式
- JNI 传递结构体参数
- Python多线程 - 使用TheadLocal传递参数
- EJB---->消息驱动bean--Topic 消息的发送与接收(Pub/sub 消息传递模型)
- Delphi过程函数传递参数的几种方式
- QT信号和槽参数传递复杂结构的数据
- c# 多线程 Thread传递参数
- Delphi 函数传递参数的不同方式
- c# 多线程传递参数以及任务