问题起源:最近开发了一个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.