[英]Is TCustomClientDataSet CloneCursor thread safe?
我已经读过克隆的TClientDataSets是线程安全的,如果克隆是只读的(没有记录的发布或重新加载数据)
但是我关心CloneCursor方法本身; 该方法以调用源DataSet的SetNotifyCallback方法结束,如果FNotifyCallback为False,该方法将回调方法传递给它的IDSCursor:
procedure TCustomClientDataSet.SetNotifyCallback;
begin
if not FNotifyCallback then
begin
Check(FDSCursor.SetNotifyCallBack(IntPtr(Self), @TCustomClientDataSet.NotifyCallback));
FNotifyCallback := True;
end;
end;
在不太可能的情况下,两个DataSet,A&B,在几乎同时克隆到DataSet C的单独线程中(DataSet C的FNotifyCallback False),A略微超前B.在A检查FNotifyCallback但之前开始执行C的SetNotifyCallBack A已在上面显示的方法中将FNotifyCallBack设置为True。
在这种情况下,DataSet C的FDSCursor SetNotifyCallback方法几乎同时被两个不同的线程调用; 一个在IDSCursor中写入变量引用的方法(我假设;没有运气找到源代码)。 不可否认,这两个调用都要求存储相同的引用,但正如标题所要求的那样,CloneCursor是否是线程安全的?
请提前接受我的谢意。
问题中出现的问题包括两个线程A和B同时克隆到C的不太可能的事件,这些代表了自C打开以来对C的CloneCursor方法的第一次调用(FNotifyCallback False)。 这导致C的IDSCursor SetNotifyCallback可能同时被两个独立的线程调用。
根据Graymatter的评论,一个解决方案是确保第一次调用C的CloneCursor发生在C的线程中。 完成此操作后,FNotifyCallback为True,并且只要C保持打开,它就会保持不变。
使用FNotifyCallback True,C的SetNotifyCallback代码解析为以下指令(在我的PC上):
006418CB cmp byte ptr [ebx+$00000290],$00
006418D2 jnz $006418fa
{code to call IDSCursor SetNotifycallback}
006418FA 5B pop ebx
006418FB C3 ret
使用FNotifyCallback True,在跳转到pop和ret指令之前,SetNotifyCallback会将FNotifyCallback的内容与零值进行比较。
冒着被殴打的风险,我相信一旦FNotifyCallback为True,那么后续对SetNotifyCallback的调用是线程安全的。
虽然问题的主体侧重于SetNotifyCallback,但问题专门针对CloneCursor。 唯一关注的其他领域(我可以看到)围绕将克隆DataSet的FDSBase分配给源(本讨论中的C)FDSBase。 这将增加源FDSBase接口的引用计数。
在我的电脑上,这解析为增加内存位置的单个指令:
inc dword ptr [eax+$04]
我假设是原子的。 另外,我无法相信,使接口的refcount线程的递增和递减安全,并不是首次提出接口时首先考虑的事情之一。
总之,一旦FNotifyCallback为True,我相信CloneCursor是线程安全的。
相当古老的问题,但我在任何地方都没有得到很好的回复,不得不自己挖掘一下。 所以在这里张贴给那些仍然可以使用这些东西的人。
CloneCursor不是线程安全的,至少在我最近测试过的Delphi 2007中。 如果您在多个线程中调用CloneCursor,其中每个线程都有自己的克隆数据集,所有这些数据集都是从同一源数据集克隆的,您将获得AV或其他错误。 很容易重现这一点:只需创建两个或多个线程,这样就可以在while循环中克隆相同的数据集,并且最多只能在几秒钟内得到错误。 但是您可以使用关键部分保护对CloneCursor的调用,并且可以在关键部分之外使用您的克隆。
现在,你建议的另一种方法是,在两个或多个线程中将不同的源克隆到同一个克隆数据集,这对我来说没有意义,我甚至不打扰测试,看看是否会引发错误,因为这种用法似乎已经被设计错了。 如果您需要这样的用法,我建议您直接进入CriticalSection。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.