日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DLL内线程同步主线程研究(子线程代码放到主线程执行)

發布時間:2024/4/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DLL内线程同步主线程研究(子线程代码放到主线程执行) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

DLL內線程同步主線程研究(子線程代碼放到主線程執行)

?

?????? 我們在實際項目中經常會用到多線程編程,比如Socket編程等,在創建的線程內同步主線程一般使用Synchronize方法實現子線程操作放到主線程執行,Synchronize使用非常方便,且在2009及以上版本都可以使用匿名方法,這樣給我們多線程帶來了很大的便利。但是實踐證明Synchronize只在主程序內正常工作。如果在主程序加載的DLL程序內運行使用Synchronize方法要求的條件比較苛刻,它要求必須把DLL程序拷掛到主程序,同時DLL內有窗體狀態需為Modal或者主程序內窗體無一顯示。具體見下:

?

主程序:

unit MainFrm;

?

interface

?

uses

? Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

? Dialogs, StdCtrls;

?

type

? TMainForm = class(TForm)

??? btn1: TButton;

??? procedure btn1Click(Sender: TObject);

? private

??? { Private declarations }

? public

??? { Public declarations }

? end;

?

var

? MainForm: TMainForm;

?

implementation

?

{$R *.dfm}

?

procedure TMainForm.btn1Click(Sender: TObject);

var

? FHandle:THandle;

? OpenDLLWindow:procedure(AMainHandle:Integer);stdcall;

begin

? FHandle:=LoadLibrary(PChar('DLLPrj.dll'));

? if FHandle>0 then

? begin

??? OpenDLLWindow:= GetProcAddress(FHandle,PChar('OpenDLLWindow'));

?

??? if Assigned(OpenDLLWindow) then

??? begin

????? OpenDLLWindow(Application.Handle);

??? end;

? end

? else

??? ShowMessage('加載DLL失敗!');

end;

?

end.

?

DLL程序:

unit DLLFrm;

?

interface

?

uses

? Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

? Dialogs;

?

type

? TDLLForm = class(TForm)

??? procedure FormShow(Sender: TObject);

??private

??? { Private declarations }

? public

??? { Public declarations }

? end;

?

type

? TDLLThread = class(TThread)

? protected

??? procedure Execute; override;

? end;

?

var

? DLLForm: TDLLForm;

?

implementation

?

{$R *.dfm}

?

procedure TDLLThread.Execute;

var

? Count:Integer;

? tp:TThreadProcedure;

begin

? Count:=0;

? while True do

? begin

??? try

????? Synchronize(

??????? procedure

??????? begin

????????? ShowMessage(IntToStr(Count));

????????? Count:=Count+2000;

??????? end

????? );

??? except

????? // ignore error

??? end;

?

??? Sleep(2000);// 暫停兩秒

? end;

end;

?

procedure OpenDLLWindow(AMainHandle:Integer);stdcall;

begin

? if DLLForm=nil then

DLLForm:=TDLLForm.Create(Application);

?

// 拷掛到主程序

? Application.Handle:=AMainHandle;

? DLLForm.ShowModal;

? //DLLForm.Show;

end;

exports OpenDLLWindow;

?

?

procedure TDLLForm.FormShow(Sender: TObject);

var

? DLLThread :TDLLThread;

begin

? DLLThread:=TDLLThread.Create(False);

end;

?

end.

以上代碼使用了Synchronize方法進行同步主線程,可以正常運行。但如果我們把DLL項目內方法OpenDLLWindow內去掉Application.Handle:=AMainHandle;或者把代碼DLLForm.ShowModal;改為DLLForm.Show;這樣線程同步主線程時將被阻塞。

?????? 這樣看來如果如果在DLL項目內如果被主程序加載后窗體顯示方式不是Modal的話我們將無法使用便利的Synchronize方法。這樣我們使用SendMessage往主線程發送消息成為必須,如我們把DLL工程內代碼更改如下:

unit DLLFrm;

?

interface

?

uses

? Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

? Dialogs;

?

type

? TDLLForm = class(TForm)

??? procedure FormShow(Sender: TObject);

? private

??? { Private declarations }

? public

??? { Public declarations }

??? procedure WMRefreshForm(var Msg: TMessage); message WM_USER+100;

? end;

?

type

? TDLLThread = class(TThread)

? protected

??? procedure Execute; override;

? end;

?

var

? DLLForm: TDLLForm;

?

implementation

?

{$R *.dfm}

?

procedure TDLLThread.Execute;

var

? Count:Integer;

? tp:TThreadProcedure;

begin

? Count:=0;

? while True do

? begin

??? try

????? SendMessage(DLLForm.Handle, WM_USER+100, Count, 0);

????? Count:=Count+2000;

??? except

????? // ignore error

??? end;

?

??? Sleep(2000);

? end;

end;

?

procedure OpenDLLWindow(AMainHandle:Integer);stdcall;

begin

? if DLLForm=nil then

??? DLLForm:=TDLLForm.Create(Application);

?

? // 拷掛到主程序

? //Application.Handle:=AMainHandle;

? //DLLForm.ShowModal;

? DLLForm.Show;

end;

exports OpenDLLWindow;

?

?

procedure TDLLForm.FormShow(Sender: TObject);

var

? DLLThread :TDLLThread;

begin

? DLLThread:=TDLLThread.Create(False);

end;

?

procedure TDLLForm.WMRefreshForm(var Msg: TMessage);

begin

? if Msg.Msg=WM_USER+100 then

? begin

??? ShowMessage(IntToStr(Msg.WParam));

? end;

end;

?

end.

這樣我們的DLL程序就工作正常了,這也是目前的常用方法。但是如果我們在線程內有頻繁的同步操作,或者這些同步操作會用到比較多的線程內變量,這樣SendMessage就顯得麻煩又吃力。如果我們在線程執行方法內能自定義匿名方法就像使用Synchronize那樣的話我們的代碼量將大大減少,且編程過程將大大簡化,這樣我們就想到了把匿名方法的指針作為SendMessage的一個參數傳到自定義的消息內,然后在自定義消息內執行這個匿名方法。令我們慶幸的是這樣是行的通的。如我們把DLL工程內代碼修改如下:

unit DLLFrm;

?

interface

?

uses

? Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

? Dialogs;

?

type

? TDLLForm = class(TForm)

??? procedure FormShow(Sender: TObject);

? private

??? { Private declarations }

? public

??? { Public declarations }

??? procedure WMRefreshForm(var Msg: TMessage); message WM_USER+100;

? end;

?

type

? TDLLThread = class(TThread)

? protected

??? procedure Execute; override;

? end;

?

var

? DLLForm: TDLLForm;

?

implementation

?

{$R *.dfm}

?

procedure TDLLThread.Execute;

var

? Count:Integer;

? tp:TThreadProcedure;

begin

? Count:=0;

? while True do

? begin

??? try

????? SendMessage(DLLForm.Handle, WM_USER+100,Integer(

??????? @procedure

??????? begin

????????? ShowMessage(IntToStr(Count));

????????? Count:=Count+2000;

??????? end),0

????? );

?

//????? tp:= procedure

//????? begin

//??????? ShowMessage(IntToStr(Count));

//??????? Count:=Count+2000;

//????? end;

//????? SendMessage(DLLForm.Handle, WM_USER+100,Integer(@tp),0);

??? except

????? // ignore error

??? end;

?

??? Sleep(2000);

? end;

end;

?

procedure OpenDLLWindow(AMainHandle:Integer);stdcall;

begin

? if DLLForm=nil then

??? DLLForm:=TDLLForm.Create(Application);

?

? // 拷掛到主程序

? //Application.Handle:=AMainHandle;

? //DLLForm.ShowModal;

? DLLForm.Show;

end;

exports OpenDLLWindow;

?

?

procedure TDLLForm.FormShow(Sender: TObject);

var

? DLLThread :TDLLThread;

begin

? DLLThread:=TDLLThread.Create(False);

end;

?

procedure TDLLForm.WMRefreshForm(var Msg: TMessage);

begin

? if Msg.Msg=WM_USER+100 then

? begin

??? TThreadProcedure(Pointer(Msg.WParam)).Invoke;

? end;

end;

?

end.

?

如果方法TDLLThread.Execute改為

procedure TDLLThread.Execute;

var

? Count:Integer;

? tp:TThreadProcedure;

begin

? Count:=0;

? while True do

? begin

??? try

????? tp:= procedure

????? begin

??????? ShowMessage(IntToStr(Count));

??????? Count:=Count+2000;

????? end;

????? SendMessage(DLLForm.Handle, WM_USER+100,Integer(@tp),0);

??? except

????? // ignore error

??? end;

??? Sleep(2000);

? end;

end;

那么TDLLForm.WMRefreshForm方法需改為:

procedure TDLLForm.WMRefreshForm(var Msg: TMessage);

begin

? if Msg.Msg=WM_USER+100 then

? begin

??? TThreadProcedure(Pointer(Msg.WParam)^).Invoke;

? end;

end;

這點需要注意。

?????? 這樣一來我們在DLL程序內只需要稍加修改就可以實現Synchronize一模一樣的效果,盡情使用匿名方法給我們帶來的方便,以上代碼在Delphi2010內通過調試,分享給大家,不足之處往指教。

???????????????????????????????????????????????????????????????????????????? 作者:張皓

??????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????? 2010-7-30

轉載于:https://www.cnblogs.com/zhmore/archive/2010/07/29/1787474.html

總結

以上是生活随笔為你收集整理的DLL内线程同步主线程研究(子线程代码放到主线程执行)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。