繁体   English   中英

TCustomClientDataSet CloneCursor线程是否安全?

[英]Is TCustomClientDataSet CloneCursor thread safe?

我已经读过克隆的TClientDataSets是线程安全的,如果克隆是只读的(没有记录的发布或重新加载数据)

Delphi - TClientDataset线程安全吗?

但是我关心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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM