Delphi7 从子线程中发送消息到主线程触发事件执…

2008-04-09 04:23:21来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

在对数据库的操作时,有时要用一个子线程来进行后台的数据操作。比如说数据备份,转档什么的。在主窗口还能同是进行其它操作。而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上(可视),同时进行日志处理等。我用的是下面的方法:

[1]用到的API函数:
RegisterWindowsMessage
----------------------
函数功能:该函数定义一个新的窗口消息,该消息确保在系统中是唯一的。返回的消息值可在调用函数SendMessage或PostMessage时使用。
function RegisterWindowMessage(lpString: PChar): UINT; stdcall;

SendNotifyMessage
----------------------
函数功能:该函数将指定的消息发送到一个窗口。
如果该窗口是由调用线程创建的;此函数为该窗口调用窗口程序,
并等待窗口程序处理完消息后再返回。
如果该窗口是由不同的线程创建的,此函数将消息传给该窗口程序,
并立即返回,不等待窗口程序处理完消息。
SendNotifyMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);

BroadcastSystemMessage
----------------------
函数功能:该函数发送消息给指定的接受者。
接受者可以是一个应用程序、安装驱动器、网络驱动器、系统级设备驱动器
或这些系统组件的组合。

[2]过程:
type
TForm1 = class(TForm)
...............
...............
private
Msg: Cardinal;
protected
procedure WndProc(var Message: TMessage); override;
public
...............
...............
end;

var
Form1: TForm1;
MsgStrList: TStringList;
MsgStrLock : TCriticalSection;

implementation
uses ThreadCommunication_Unit;
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Msg := RegisterWindowMessage(''''wm_threadmsg'''');
MsgStrList := TStringList.Create;
end;

procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = Msg then begin
MsgStrLock.Enter;
if MsgStrList.Count > 0 then begin
Caption := MsgStrList.Strings[0];
MsgStrList.Delete(0);
end;
MsgStrLock.Leave;
ShowMessage(''''收到消息了'''' inttostr(Message.Msg));
end
else begin
inherited;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TThreadCommunication.Create(Msg,Memo1);
end;
...............
...............

initialization
MsgStrLock := TCriticalSection.Create;
finalization
MsgStrLock.Free;
end.

一个子线程类的单元:
unit ThreadCommunication_Unit;
interface

uses
Classes,StdCtrls;

type
TThreadCommunicaiton = class(TThread)
private
FMsg : Cardinal;
FMemo: TMemo;
protected
procedure Execute; override;
procedure SendMsg;
public
constructor Create(aMsg:Cardinal;am:TMemo);virtual;
end;

implementation
uses Messages,Windows, Dialogs,SysUtils, ThreadMsg;

{ TThreadCommunicaiton }

constructor TThreadCommunicaiton.Create(aMsg: Cardinal; am:TMemo);
begin
inherited Create(True);
FMsg := aMsg;
FMemo:= am;
FreeOnTerminate :=True;
Resume;
end;

procedure TThreadCommunicaiton.Execute;
begin
Synchronize(SendMsg);
end;


procedure TThreadCommunicaiton.SendMsg;
var
M: TMessage;
B: DWord;
d: integer;
begin
{ Place thread code here }
sleep(50);
M.Msg := FMsg;
B := BSM_ALLCOMPONENTS;

MsgStrLock.Enter;
MsgStrList.Add(''''子线程子柄:'''' inttostr(ThreadID) '''' 用BroadcastSystemMessage发送'''');
d := MsgStrList.Count;
MsgStrLock.Leave;

BroadcastSystemMessage(BSF_POSTMESSAGE, @B , M.Msg, M.WParam, M.LParam );
FMemo.Lines.Add(''''子线程子柄:'''' inttostr(ThreadID) '''' 用BroadcastSystemMessage发送'''' inttostr(d));

end;

end.

我在窗口上放有一Memo控件,可以显示一些信息。
同时我定义了一个全局的TStringList的变量,用于存在要从子线程传出的一些值。用BroadcaseSystemMessage发送消息,而消息号由创建子线程时传入。而消息号在FormCreate中用RegisterWindowsMessage定义,并获得一个消息号。
而消息触发后的事件处理写在WndProc中。
这里将子线程传出的字符串写入窗口的标题。

而TStringList的变量作为临界区使用, 因为当两个线程访问全局量时,为防止它们同时执行,需要使用线程同步。

用TCriticalSection进行操作。
Enter,进入临界区
Leave,离开临界区
这样可以正确的处理从子线程发来的消息。

如果是用SendNotifyMessage函数发送消息的话。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:两个delphi下遍历指定目录下指定类型文件的函数

下一篇:怎样检测你的IE使用的代理服务器