在對數據庫的操作時,有時要用一個子線程來進行後台的數據操作。比如說數據備份,轉檔什麽的。在主窗口還能同是進行其它操作。而有時後台每處理一個數據文件,要向主窗口發送消息,讓主窗口實時顯示處理進度在窗口上(可視),同時進行日志處理等。我用的是下面的方法:
[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函數發送消息的話。
用法如下:
M.Msg := FMsg;
SendNotifyMessage(HWND_BROADCAST,M.Msg , M.WParam, M.LParam);
參數爲HWND_BROADCAST,則消息將被發送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發送到子窗口。
由于是用SendNotifyMessage將消息發送到主窗口,而主窗口所在線程與調用線程是同一個線程,所以要等待窗口程序處理完消息後再返回。才會執行子線程中的:
FMemo.Lines.Add('子線程子柄:'+inttostr(ThreadID)+ ' 用SendNotifyMessage發送');
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
在對數據庫的操作時,有時要用一個子線程來進行後台的數據操作。比如說數據備份,轉檔什麽的。在主窗口還能同是進行其它操作。而有時後台每處理一個數據文件,要向主窗口發送消息,讓主窗口實時顯示處理進度在窗口上(可視),同時進行日志處理等。我用的是下面的方法:
[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函數發送消息的話。
用法如下:
M.Msg := FMsg;
SendNotifyMessage(HWND_BROADCAST,M.Msg , M.WParam, M.LParam);
參數爲HWND_BROADCAST,則消息將被發送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發送到子窗口。
由于是用SendNotifyMessage將消息發送到主窗口,而主窗口所在線程與調用線程是同一個線程,所以要等待窗口程序處理完消息後再返回。才會執行子線程中的:
FMemo.Lines.Add('子線程子柄:'+inttostr(ThreadID)+ ' 用SendNotifyMessage發送');