【问题标题】:Can I execute TDataSet.DisableControls in worker thread without wrapping it with Synchronize()?我可以在工作线程中执行 TDataSet.DisableControls 而不用 Synchronize() 包装它吗?
【发布时间】:2011-11-27 18:28:15
【问题描述】:

首先,我不确定允许工作线程禁用控件是否是一个好的设计。但是,我很好奇我可以在不与 GUI 同步的情况下安全地做到这一点吗?

TDataSet 中的代码如下所示:

procedure TDataSet.DisableControls;
begin
  if FDisableCount = 0 then
  begin
    FDisableState := FState;
    FEnableEvent := deDataSetChange;
  end;
  Inc(FDisableCount);
end;

所以看起来很安全。在 EnableControls 的情况下情况会有所不同。但是 DisableControls 似乎只会增加锁定计数器和分配在 EnableControls 期间触发的事件。

你怎么看?

【问题讨论】:

  • 如果您不使用数据对齐进行编译,即使 Incby 本身也不是线程安全的。我强烈建议不要使用以某种方式链接到 GUI 控件的任何控件
  • 进一步,考虑以下场景:线程进入,FDisableCount = 0,FDisableState = FState。发生上下文切换,您的主线程减少 FDisableCount 并更改 FDisableState(我想这就是 EnableControls 中会发生的情况,还没有看过)。发生上下文切换,您的线程再次运行,但现在使用错误的 FDisableState。
  • 感谢 Lieven 指出这一点。

标签: multithreading delphi synchronization dataset delphi-2009


【解决方案1】:

这样做看起来很安全,但可能会出错,因为这些标志用于代码中,而这些代码可能在您从线程调用此方法时正在执行。

我会同步对 DisableControls 的调用,因为您希望线程仅在没有控件使用它时才开始使用此数据集。 对 EnableControls 的调用也可以同步,或者您可以使用 PostMessage 将消息发布到表单。这样,线程就不必等待主线程了。

但我的直觉告诉我,最好不要对 GUI 和线程使用相同的数据集。

【讨论】:

    【解决方案2】:

    无需查看实际代码:这可能是安全的,只要您可以确定主线程当前不访问 FDisableCount、FDisableState 和 FEnableEvent。这里可能存在竞争条件。

    我仍然建议您从主线程中调用 DisableControls。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多