- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题有点长,但我们开始吧。有一个 FormatDateTime 版本据说是线程安全的,因为您使用
GetLocaleFormatSettings(3081, FormatSettings);
获取一个值,然后你可以像这样使用它;
FormatDateTime('yyyy', 0, FormatSettings);
现在想象两个计时器,一个使用 TTimer(间隔为 1000 毫秒),然后像这样创建另一个计时器(间隔为 10 毫秒);
CreateTimerQueueTimer
(
FQueueTimer,
0,
TimerCallback,
nil,
10,
10,
WT_EXECUTEINTIMERTHREAD
);
现在最后一点,如果在回调和计时器事件中你有以下代码;
for i := 1 to 10000 do
begin
FormatDateTime('yyyy', 0, FormatSettings);
end;
请注意,没有分配。这几乎会立即产生访问违规,有时会在 20 分钟后,无论如何,在随机的地方。现在,如果您在 C++Builder 中编写该代码,它永远不会崩溃。我们使用的 header 转换是 JEDI JwaXXXX 的 header 转换。即使我们在 Delphi 版本中对代码加锁,也只会延迟不可避免的事情。我们已经查看了原始的 C 头文件,看起来一切都不错,C++ 使用 Delphi 运行时是否有一些不同的方式? FormatDatTime 的线程安全版本看起来是可重入的。来自以前可能见过此内容的任何人的任何想法或想法。
更新:
为了缩小范围,FormatSettings 作为常量传入,因此它们是否使用相同的副本是否重要(因为事实证明在函数调用中传递本地版本会产生相同的问题)?此外,采用 FormatSettings 的 FormatDateTime 版本不会调用 GetThreadLocale,因为它已经在 FormatSettings 结构中具有区域设置信息(我通过单步执行代码进行了双重检查)。
我提到没有分配是为了明确表示没有共享存储被访问,因此不需要锁定。
WT_EXECUTEINTIMERTHREAD 用于简化问题。我的印象是您应该只将它用于非常短的任务,因为这可能意味着如果它运行时间较长,它可能会错过下一个间隔?
如果您使用普通的旧 TThread,则不会出现问题。我在这里得到的结果是,我认为使用 TThread 或 TTimer 可以工作,但使用在 VCL 外部创建的线程则不行,这就是为什么我问 C++ Builder 使用 VCL/Delphi RTL 的方式是否存在差异。
顺便说一句,前面提到的这段代码也会失败(但需要更长的时间),过了一会儿,CS := TCriticalSection.Create;
CS.Acquire;
for i := 1 to LoopCount do
begin
FormatDateTime('yyyy', 0, FormatSettings);
end;
CS.Release;
现在我真的不明白,我按照建议写了这个;
function ReturnAString: string;
begin
Result := 'Test';
UniqueString(Result);
end;
然后在每种类型的计时器内,代码是:
for i := 1 to 10000 do
begin
ReturnAString;
end;
这会导致相同类型的故障,正如我之前所说,故障永远不会出现在 CPU 窗口等的同一位置。有时它是访问冲突,有时可能是无效的指针操作。顺便说一句,我正在使用 Delphi 2009。
更新2:
Roddy(下)指出 Ontimer 事件(不幸的是 Winsock,即 TClientSocket)使用 Windows 消息泵(顺便说一句,如果有一些使用 IOCP 和 Overlapping IO 的不错的 Winsock2 组件会很好),因此推送远离它。但是,有谁知道如何查看 CreateQueueTimerQueue 上设置了哪种线程本地存储?感谢您花时间思考并回答这个问题。
最佳答案
我不确定对我自己的问题发布“答案”是否是一种好的形式,但这似乎合乎逻辑,如果这不酷,请告诉我。
我想我已经找到了问题所在,线程本地存储的想法引导我跟踪了一堆线索,我发现了这条神奇的线;
IsMultiThread := True;
来自帮助;
“IsMultiThread 设置为 true 表示内存管理器应支持多线程。BeginThread 和类工厂将 IsMultiThread 设置为 true。”
当然,这不能通过使用 TTimer 使用单个主 VCL 线程来设置,但是当您使用 TThread 时它会为您设置。如果我手动设置,问题就会消失。
在 C++Builder 中,我不使用 TThread,但它通过使用以下代码出现;
if (IsMultiThread) {
ShowMessage("IsMultiThread is True!");
}
这是自动为您设置的。
我真的很高兴人们的意见,这样我就能找到这个,我希望它能对其他人有所帮助。
关于multithreading - Delphi Win API CreateTimerQueueTimer 线程和线程安全 FormatDateTime 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/352543/
我在我的应用程序中使用计时器队列,并将指向我自己的 C++ 计时器对象之一的指针作为“参数”传递给回调(在 CreateTimerQueueTimer 中)。然后,我在回调中对对象调用虚拟方法。 Ti
我需要暂停使用 win32 API 的 CreateTimerQueueTimer 函数创建的计时器,但我找不到暂停计时器的方法。有人知道这是否可能吗? 最佳答案 相信你可以调用ChangeTimer
我的应用程序需要高分辨率(比 1 毫秒更准确)计时。 Windows 中的可等待计时器精确到(或可以精确到毫秒),但如果我需要精确的周期,比如 35.7142857141 毫秒,即使是 36 毫秒周期
我使用 Windows 多媒体 dll 创建了一个高分辨率计时器 timSetEvent() 但是timeSetEvent()页面推荐使用: CreateTimerQueueTimer() 如何使用
这个问题有点长,但我们开始吧。有一个 FormatDateTime 版本据说是线程安全的,因为您使用 GetLocaleFormatSettings(3081, FormatSettings); 获取
我正在努力实现 +/- 毫秒计时精度。我希望线程之间的时间为 10 毫秒,但当我测量时间时,我得到的结果接近 15 毫秒。 我想了解问题是由于我测量时间的方式引起的,还是我测量时间准确并且 Creat
我正在尝试使用 CreateTimerQueueTimer(...) 每隔一段时间运行一个函数。 我正在使用来自 MSDN 的示例,主要是这一行与我有关: CreateTimerQueueTimer(
我是一名优秀的程序员,十分优秀!