问题起源:最近开发了一个DCOM服务器,内部有个队列任务。客户端可以连接调用以添加任务到队列。现在有个问题是当客户端调用完断开连接后,DCOM服务器的队列任务还没执行完毕DCOM就退出了。请问有什么办法可以让队列执行完才退出呢?
简单的解决方案演示:演示是通过增加一个方法Method1,被用户调用后,记下自己当前的ThreadID(GetCurrentThradId获得),然后调用_Addref增加引用计数。
启动一个线程,在线程当中只做一个事,等待15秒,线程置为FreeOnTerminate,并且OnTerminated事件置过程放在COM对象当中,事件发生时(线程是主线程),调用_Release释放引用计数。此时COM的处理线程会在等待消息,所以不会去释放对象,但是此时可以PostThreadMessage(ThreadID,0,0)唤醒线程,线程就会检查计数,(而此时计数正好为0)并释放对象。
unit Unit4;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, Project2_TLB, StdVcl;
type
Tcc = class(TRemoteDataModule, Icc)
private
{ Private declarations }
ThrdID: DWORD;
procedure OnThradTerminated(Sender: TObject);
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
procedure Method1; safecall;
public
{ Public declarations }
end;
//一个定时器线程
TMyThread = Class(TThread)
protected
procedure Execute;override;
End;
implementation
{$R *.DFM}
procedure TMyThread.Execute;
var
I: Integer;
begin
I := 15000;//15秒
while I>0 do begin
Sleep(15);
Dec(I,15);
end;
end;
class procedure Tcc.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;
procedure Tcc.Method1;
var
Thd: TMyThread;
begin
//添加引用计数
_AddRef;
//取得当前线程的ID,以方便释放时唤醒
ThrdID := GetCurrentThreadId;
//创建一个线程用于15秒后释放计数,以模拟线程异步操作
Thd := TMyThread.Create(True);
//置线程线程事件过程,以执行释放计数的过程代码
Thd.OnTerminate := OnThradTerminated;
//线程自动销毁
Thd.FreeOnTerminate := True;
//唤醒线程
Thd.Resume;
end;
procedure Tcc.OnThradTerminated(Sender: TObject);
begin
//线程结束,表示异步任务完成,释放计数
_Release;
//唤醒COM线程
PostThreadMessage(ThrdID,0,0,0);
end;
initialization
TComponentFactory.Create(ComServer, Tcc,
Class_cc, ciMultiInstance, tmApartment);
end.