【Delphi-多线程笔记】关于同步到主线程的记录。

昨天在D7下面晚上碰到一个问题,发现在主程序关闭的时候,出现了进程无法彻底退出,调试后发现safeLogger阻塞在PostMessage之后,等待主线程处理的状态。

D2007下面只要在Destroy的时候把sfLogger.Enable := false就好了,即使后面有投递请求的情况也不会再进行处理。

但是D7下面发现不奏效,发现D7下面在OnClose的时候,再投递关于PostMessage和sync到主线程的函数都会卡死线程。无奈,只能在关闭的时候就设定。

XE6下面发现在Destroy和OnClose时投递都没问题。

 

总结:

  D7在主窗体点击关闭后,就不要再有Sync同步函数和sendMessage了,当然PostMessage也不会执行了。

  D2007在主窗体Destroy后,就不要再有Sync同步函数和sendMessage了,当然PostMessage也不会执行了。

  XE6貌似不会造成线程死锁和死等。

【DIOCP3-说明书】iocpTask中添加信号触发任务功能

【应用场景】

信号触发任务是为了可以重复触发信号对应的任务,而且可以把回调函数的绑定和触发信号分离,比如你可以在主窗体中注册信号对应的事件,然后在任何的线程和单元中安全的触发信号。

 

【使用DEMO】

主窗体中注册信号绑定回调函数

//注册信号,并绑定信号对应的回调函数
iocpTaskManager.registerSignal(1, OnSignalWork);


// 回调事件函数
procedure TfrmMain.OnSignalWork(pvTaskRequest:TIocpTaskRequest);
var
  lvData:TSimpleDataObject;
begin
  lvData:= TSimpleDataObject(pvTaskRequest.TaskData);
  if GetCurrentThreadId = MainThreadID then
  begin
    Memo1.Lines.Add('exeucte signal task in main thead:' + lvData.DataString1);
  end else
  begin
    logMessage('exeucte signal task in thread:' + lvData.DataString1);
  end;
end;

 

 

 // 可以在任何的地方安全的触发信号
 iocpTaskManager.SignalATask(1, TSimpleDataObject.Create('signal param'), ftFreeAsObject);

 

【相关函数】

注册函数:

procedure registerSignal(pvSignalID: Integer; pvTaskWork: TOnTaskWork);

pvSignalID      注册的信号ID, 重复注册时会引发异常。

pvTaskWork   信号对应的回调函数

 

触发函数:

procedure SignalATask(pvSignalID: Integer; pvTaskData: Pointer = nil;
        pvDataFreeType: TDataFreeType = ftNone; pvRunInMainThread: Boolean = False;
        pvRunType: TRunInMainThreadType = rtSync);

 

pvSignalID             信号ID

pvTaskData          触发信号带入的一些参数数据,在回调函数中可以获取(pvTaskRequest.TaskData)

pvDataFreeType   参数数据在任务执行完成或者投递失败后释放的方式(; , 

                             ftNone, 不做任何处理

                             ftFreeAsObject 调用TObject(TaskData).Free

                             ftUseDispose,    调用Dispose(TaskData)

pvRunInMainThread 是否在主线程中执行回调函数

pvRunType         主线程同步的方式,不带包的DLL中不能用rtSync模式