2012-08-30 67 views
1

我已经注册了我的申请ARR。假设我的应用程序有一个IdTCPServer,它使用VSPE从串口读取数据,并将其添加到ClientDataSet。如果主线程冻结,ARR将调用我的ApplicationRecoveryCallback()。我可以安全地访问恢复回调函数中的IdTCPServer吗?我希望它停止,以便我可以在重新启动之前将我的ClientDataSet保存到磁盘。我可以这样简单地写我的功能吗?如何防止ApplicationRecoveryCallback()中的死锁?

function RecoveryFunction(pvParameter: Pointer): DWORD; stdcall; 
var 
    ContinueRecovery: Boolean; 
begin 
    Result := 0; // happy compiler ;-) 
    repeat 
    ApplicationRecoveryInProgress(ContinueRecovery); 
    if not ContinueRecovery then 
     ApplicationRecoveryFinished(False); 
    until frmInstrument.CriticalSection.TryEnter; 
    frmInstrument.IdTCPServer.Active := False; 
    frmInstrument.CDS.SaveToFile(RecoveryFile); 
    ApplicationRecoveryFinished(True); 
end; 
+0

为什么不停止应用程序冻结在第一位? –

+0

@DavidHeffernan好问题,但这是最后一项节省宝贵数据的努力,如果我的应用程序将会死亡。我从串口收集的数据来自一堆没有内存的医疗实验室仪器,所以当我收到一个包时,我应该用我的生活来保护它,可以这么说。 –

+4

你可以立即将它写入磁盘来保护它。当你这样做时,不需要恢复,因为你已经保存了所有可用的东西。 ARR文件就是这样建议的。 –

回答

1

我不会那样写的。当程序停止响应时调用此函数。对于你所知道的,它停止了响应,因为其他东西已经停滞不前,等待着同一个关键部分。

如果您希望即使在程序挂起时也能够访问您的数据,那么当您允许读取数据时,您需要使用无锁定方式来检测。使用事务日志模型。原子上更新的东西,表明有多少数据是有效的。当您输入恢复功能时,请阅读该值,并尽可能多地保存它所说的值。不要打扰超出这一点的阅读,因为你不能确定它没有损坏,并且你的程序首先崩溃的原因。

+0

我可以在恢复回调函数中访问VCL类吗?我的表单,数据模块等? –

+0

当然。为什么不?这是你程序的一部分。虽然访问可能不可靠,因为你的程序已经挂起或崩溃。 –

+0

我的意思是如果可能存在访问违规。例如,我需要在访问任何数据之前停止所有正在运行的线程,可能会强制执行。 –

1

如果您将串行端口和CDS逻辑移出主线程,则可以降低应用程序无响应的可能性并使ARR完全启动。主线程只能用于UI逻辑,需要一段时间才能运行的业务逻辑更好地在工作线程中提供服务。

+0

我的CDS逻辑在'IdTCPServerExecute'中,我使用'VSPE'将串口路由到TCP,因此我的主线程仅用于UI –

+0

“我的主线程仅用于UI” - 如果这是真的,不会冻结。 –