DCOM当中保证异步作业不因远端COM客户断开而中止的解决方案(Delphi)

来源:互联网 发布:gitv电视直播软件 编辑:程序博客网 时间:2024/04/27 20:51

问题起源:最近开发了一个DCOM服务器,内部有个队列任务。客户端可以连接调用以添加任务到队列。现在有个问题是当客户端调用完断开连接后,DCOM服务器的队列任务还没执行完毕DCOM就退出了。请问有什么办法可以让队列执行完才退出呢?

简单的解决方案演示:演示是通过增加一个方法Method1,被用户调用后,记下自己当前的ThreadID(GetCurrentThradId获得),然后调用_Addref增加引用计数。
启动一个线程,在线程当中只做一个事,等待15秒,线程置为FreeOnTerminate,并且OnTerminated事件置过程放在COM对象当中,事件发生时(线程是主线程),调用_Release释放引用计数。此时COM的处理线程会在等待消息,所以不会去释放对象,但是此时可以PostThreadMessage(ThreadID,0,0)唤醒线程,线程就会检查计数,(而此时计数正好为0)并释放对象。

  1. unit Unit4;
  2. {$WARN SYMBOL_PLATFORM OFF}
  3. interface
  4. uses
  5.   Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
  6.   DBClient, Project2_TLB, StdVcl;
  7. type
  8.   Tcc = class(TRemoteDataModule, Icc)
  9.   private
  10.     { Private declarations }
  11.     ThrdID: DWORD;
  12.     procedure OnThradTerminated(Sender: TObject);
  13.   protected
  14.     class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
  15.     procedure Method1; safecall;
  16.   public
  17.     { Public declarations }
  18.   end;
  19.   //一个定时器线程
  20.   TMyThread = Class(TThread)
  21.     protected
  22.       procedure Execute;override;
  23.   End;
  24. implementation
  25. {$R *.DFM}
  26. procedure TMyThread.Execute;
  27. var
  28.   I: Integer;
  29. begin
  30.   I := 15000;//15秒
  31.   while I>0 do begin
  32.     Sleep(15);
  33.     Dec(I,15);
  34.   end;
  35. end;
  36. class procedure Tcc.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
  37. begin
  38.   if Register then
  39.   begin
  40.     inherited UpdateRegistry(Register, ClassID, ProgID);
  41.     EnableSocketTransport(ClassID);
  42.     EnableWebTransport(ClassID);
  43.   end else
  44.   begin
  45.     DisableSocketTransport(ClassID);
  46.     DisableWebTransport(ClassID);
  47.     inherited UpdateRegistry(Register, ClassID, ProgID);
  48.   end;
  49. end;
  50. procedure Tcc.Method1;
  51. var
  52.   Thd: TMyThread;
  53. begin
  54.   //添加引用计数
  55.   _AddRef;
  56.   //取得当前线程的ID,以方便释放时唤醒
  57.   ThrdID := GetCurrentThreadId;
  58.   //创建一个线程用于15秒后释放计数,以模拟线程异步操作
  59.   Thd := TMyThread.Create(True);
  60.   //置线程线程事件过程,以执行释放计数的过程代码
  61.   Thd.OnTerminate := OnThradTerminated;
  62.   //线程自动销毁
  63.   Thd.FreeOnTerminate := True;
  64.   //唤醒线程
  65.   Thd.Resume;
  66. end;
  67. procedure Tcc.OnThradTerminated(Sender: TObject);
  68. begin
  69.   //线程结束,表示异步任务完成,释放计数
  70.   _Release;
  71.   //唤醒COM线程
  72.   PostThreadMessage(ThrdID,0,0,0);
  73. end;
  74. initialization
  75.   TComponentFactory.Create(ComServer, Tcc,
  76.     Class_cc, ciMultiInstance, tmApartment);
  77. end.
原创粉丝点击