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对象的实例被自动释放了。
韦小宝的原话:大功告成,亲一个~~~