QWorker 中作业投递时,如果需要传递一个参数,但我们如果设置jdfFreeAsObject,那么显然单次作业完成后,相关的参数就会被释放,无法传递到下一个作业。那么这个时候,我们该怎么做呢?
本文提供了一个简单的办法来解决这一问题:用 QString 单元为您提供的 TQPtr 做智能指针封装,然后作业时使用 jdfFreeAsInterface 让 QWorker 采用接口的方式来管理附加的数据。
我们先看一下声明:
IQPtr = interface(IInterface)
function Get: Pointer;
end;
TQPtrFreeEvent=procedure (AData:Pointer) of object;
TQPtrFreeEventG=procedure (AData:Pointer);
{$IFDEF UNICODE}
TQPtrFreeEventA=reference to procedure (AData:Pointer);
{$ENDIF}
TQPtr = class(TInterfacedObject, IQPtr)
private
FObject: Pointer;
FOnFree:TQPtrFreeEvent;
{$IFDEF UNICODE}
FOnFreeA:TQPtrFreeEventA;
{$ENDIF}
public
constructor Create(AObject: Pointer); overload;
destructor Destroy; override;
class function Bind(AObject: TObject): IQPtr;overload;
class function Bind(AData:Pointer;AOnFree:TQPtrFreeEvent):IQPtr;overload;
class function Bind(AData:Pointer;AOnFree:TQPtrFreeEventG):IQPtr;overload;
{$IFDEF UNICODE}
class function Bind(AData:Pointer;AOnFree:TQPtrFreeEventA):IQPtr;overload;
{$ENDIF}
function Get: Pointer;
end;
我们会用到其中的 TQPtr.Bind 函数和 IQPtr 的 Get 接口:
(1)Bind 函数用于将对象或其它类型的指针通过接口的方式进行管理,它有四种重载,如果是对象,不需要指定释放方法,如果是其它的如记录类型,就需要自己指定内存释放函数,后面三个分别对应类成员、全局函数和匿名函数版本,不进行赘述。
(2)Get 函数用于获取到咱们管理的原始的指针。
下面我们提供一个具体的例子来看一下它的用法:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,QString,QWorker, Vcl.StdCtrls;
type
TMyObject=class
public
Text:String;
destructor Destroy;override;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure DoStep1(AJob:PQJob);
procedure DoStep2(AJob:PQJob);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Workers.Post(DoStep1,Pointer(TQPtr.Bind(TMyObject.Create)),False,jdfFreeAsInterface);
end;
procedure TForm1.DoStep1(AJob: PQJob);
var
AObj:TMyObject;
begin
AObj:=IQPtr(AJob.Data).Get;
AObj.Text:='Hello,world from DoStep1';
Workers.Post(DoStep2,AJob.Data,True,jdfFreeAsInterface);
end;
procedure TForm1.DoStep2(AJob: PQJob);
var
AObj:TMyObject;
begin
AObj:=IQPtr(AJob.Data).Get;
ShowMessage(AObj.Text);
end;
{ TMyObject }
destructor TMyObject.Destroy;
begin
OutputDebugString('Object Free');
inherited;
end;
end.
上面的这段代码我们投寄了一个两步作业,第一步作业设置了 TMyObject 的一个实例的 Text 值,而第二步作业则将其用 ShowMessage 显示出来,我们没有自己释放 TMyObject 实例,但我们执行上面的代码,我们可以看到结果,截个图看下:
可以看到,在后续步骤中,参数被安全的访问,而TMyObject对象的实例被自动释放了。
韦小宝的原话:大功告成,亲一个~~~


