问题标签 [tmonitor]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1916 浏览

multithreading - TMonitor 同步/Application.ProcessMessages

我回来了另一个关于线程和同步的问题。想象一个服务器应用程序必须执行一个冗长的操作,而客户端希望他的 GUI 在等待服务器响应时保持响应。我想到了以下模式:

WorkerThread 是一个从 TThread 派生的简单类,它执行传递给其构造函数的函数,然后终止(Ready=True,结果在 Result 中)。每当单击按钮时,都会执行呈现的代码。

现在我的问题是:如果我非常快速地单击按钮两次,我会收到一些奇怪的错误,看起来很像服务器和客户端之间的通信以某种方式混淆,我想通过锁定 FTCPClient 对象来避免这种情况。Application.ProcessMessages 执行后的事件处理程序在哪个线程中?TMonitor 的锁是每个线程吗?这是否意味着如果我使用 Application.ProcessMessages 锁定不起作用?

我现在无法更好地解释它。我希望有人明白我的意思。如果没有,请随时提出问题。

编辑:对于按钮的禁用和启用:我对客户端代码一无所知。可能是按钮事件处理程序,也可能是其他东西。基本上我想隐藏客户端代码的锁定。

0 投票
4 回答
2994 浏览

delphi - TMonitor.Destroy 中的无效指针操作

我目前正在将现有的 Delphi 5 应用程序移植到 Delphi 2010。

它是加载到 Outlook 中的多线程 DLL(线程由 Outlook 生成的地方)。当通过 Delphi 2010 编译时,每当我关闭表单时,我都会在 TMonitor.Destroy 中遇到“无效指针操作”......就是 system.pas 中的那个。

由于这是一个现有的并且有点复杂的应用程序,我有很多方向要研究,而 delphi 帮助甚至没有记录几乎没有记录这个特定的 TMonitor 类开始(我将它追溯到一些 Allen Bauer 的帖子以及其他信息) ...所以我想我会先问问周围是否有人遇到过这个问题,或者对可能导致这个问题的原因有任何建议。作为记录:我没有在我的代码中明确使用 TMonitor 功能,我们在这里谈论的是 Delphi 5 代码的直接端口。

在问题发生时编辑Callstack:

0 投票
1 回答
14592 浏览

delphi - Delphi 系统单元中的 TMonitor 有什么用?

在阅读了“The Oracle at Delphi”(Allen Bauer)的文章“Simmering Unicode,让 DPL 沸腾”“Simmering Unicode,让 DPL 沸腾(第 2 部分)”之后,我只了解 Oracle :)

文章提到了Delphi并行库(DPL)、无锁数据结构、互斥锁条件变量(这篇维基百科文章转发到' Monitor(synchronization) ',然后介绍了用于线程同步的新TMonitor记录类型并描述了它的一些方法。

是否有带有示例的介绍文章,说明何时以及如何使用这种 Delphi 记录类型?网上有一些文档。

  • TCriticalSection 和 TMonitor 的主要区别是什么?

  • 我可以用PulsePulseAll方法做什么?

  • 它是否有对应的 C# 或 Java 语言?

  • RTL 或 VCL 中是否有任何代码使用这种类型(因此可以作为示例)?


更新:文章为什么 TObject 的大小在 Delphi 2009 中翻了一番?解释说 Delphi 中的每个对象现在都可以使用 TMonitor 记录来锁定,代价是每个实例增加四个字节。

看起来 TMonitor 的实现类似于Java 语言中的 Intrinsic Locks

每个对象都有一个与之关联的内在锁。按照惯例,需要对对象字段进行排他和一致访问的线程必须在访问对象之前获取对象的内在锁,然后在完成访问时释放内在锁。

Delphi 中的WaitPulsePulseAll似乎是Java 编程语言中wait()notify()notifyAll()的对应物。如果我错了,请纠正我:)


更新 2:使用和的生产者/消费者应用程序的示例代码,基于Java(tm) 教程中关于受保护方法的文章(欢迎评论):TMonitor.WaitTMonitor.PulseAll

这种应用程序在两个线程之间共享数据:创建数据的生产者和处理数据的消费者。两个线程使用共享对象进行通信。协调是必不可少的:消费者线程不得在生产者线程交付数据之前尝试检索数据,如果消费者尚未检索旧数据,则生产者线程不得尝试交付新数据。

在此示例中,数据是一系列文本消息,通过 Drop 类型的对象共享:

现在这可以按预期工作,但是有一个细节我可以改进:TMonitor.Enter(Self);我可以选择一种细粒度的锁定方法,使用(私有)“FLock”字段,而不是用 锁定整个 Drop 实例,仅在Put 和 Take 方法由TMonitor.Enter(FLock);.

如果我将代码与 Java 版本进行比较,我还注意到InterruptedExceptionDelphi 中没有可用于取消对Sleep.

更新 3:2011 年 5 月,一篇关于 OmniThreadLibrary 的博客文章提出了 TMonitor 实现中可能存在的错误。它似乎与Quality Central 中的条目有关。评论提到 Delphi 用户提供了一个补丁,但它是不可见的。

更新 4: 2013 年的一篇博客文章表明,虽然 TMonitor 是“公平的”,但它的性能比关键部分的性能差。

0 投票
1 回答
984 浏览

delphi - TMonitor.Pulse 与 TMonitor.PulseAll

Delphi Docwiki 解释说,只要调用线程释放对象, Pulse就会通知等待队列中的下一个线程,它将能够锁定指定的对象。PulseAll向等待队列中的所有线程发出信号。

发现这段代码在线程队列实现中使用了 Pulse,并给出了上面的定义,认为应该使用 PulseAll - 或者以不同的方式询问:什么时候使用 Pulse 而不是 PulseAll 是正确的?(基本问题是:我如何确定“队列中的下一个线程”始终是需要通知的线程,除非在总共只有两个线程的琐碎情况下,或者代码可以安全假设唯一等待的线程是需要通知/“脉冲”的线程)?

对于Java语言中相应的同步方法,我发现了这个问题:Java: notify() vs. notifyAll() all over again


更新:上面链接的 Java 问题有一个有趣的答案,它显示了即使在只有两个方法 put 和 get 并且使用 notify()(Pulse() 的 Java 对应物)的生产者/消费者应用程序中也会发生死锁: Java: notify() vs. notifyAll() 再一次

答案包含建议

如果您不确定要使用哪个,请使用notifyAll.

0 投票
1 回答
1473 浏览

multithreading - 在 Delphi 中,System.TMonitor.Pulse 和 TMonitor.PulseAll 实际上是做什么的

我很高兴看到 Delphi 在 Delphi 2009 中引入了 TMonitor 记录,允许您在多线程环境中锁定特定对象。令我困惑的是这种记录类型的 Pulse 和 PulseAll 方法。

例如,Delphi 帮助中的 Pulse 条目指出“通知等待队列中的下一个线程,一旦调用线程释放对象,它将能够锁定指定对象。”

真的吗?这意味着什么?我在没有使用 Pulse 的情况下使用了 TMonitor,没有任何问题。另外,在Delphi的源码中对TMonitor的一些使用从未使用过Pulse。

Pulse 和 PulseAll 方法是否仅包含在 Delphi 的 TMonitor 记录中以实现与 .NET Monitor 类的源代码级兼容性,或者它们真的有目的吗?

有两个问题(“TMonitor.Pulse vs TMonitor.PulseAll”“Delphi System unit 中的 TMonitor 有什么用处”)说明了这个问题,但我正在寻找一个明确的答案。

0 投票
0 回答
265 浏览

delphi - TMonitor 在 Delphi 2009 中是如何“损坏”的?

互联网上有一些错误报告说,在 Delphi 2009 中,TMonitor 同步类实现被严重破坏。

但是,我还找到了显示修复(补丁)的页面,例如:TMonitor bug?- http://www.thedelphigeek.com/2011/05/tmonitor-bug.html

补丁是否足以修复 TMonitor 或是否存在其他严重问题?

0 投票
1 回答
245 浏览

delphi - 在枚举器的构造函数/析构函数中使用锁定(TMonitor)是否安全?

我有简单的线程安全容器类。它具有标准的添加/删除方法。通常枚举项目被实现为:

但我想以线程安全的方式利用 for-in 支持:

我的枚举器实现将容器锁定在它的构造函数中,并在析构函数中解锁它。这是可行的,但前提是 Enumerator 的实例是在 for-in 循环的开头创建并在最后被销毁的。我在这里找到了解释:Enumerator created with for in construction 是如何被破坏的?

但是由于锁定/解锁是一项关键操作,我想知道这种用法是否可以?

这是我的实现: