【发布时间】:2021-05-06 22:29:39
【问题描述】:
我在 Windows 10 上使用 Delphi XE7。
下面的代码我用了很久了,刚刚看了SetTimer()上的文档。简单地说,我是从非 UI 线程设置计时器,但微软的文档说它们应该只在 UI 线程上设置。广泛的测试表明我的代码工作正常,但我不能相信我的系统与其他系统的行为相同,或者 Microsoft 文档是 100% 准确的。任何人都可以验证此代码是否正常?
Delphi 代码不会死锁,它几乎只是调用SetTimer()(我知道有一个竞争条件设置TTimer.FEnabled)。
hWnd
类型:HWND
要与计时器关联的窗口句柄。此窗口必须由调用线程拥有。
我想要完成的是工作线程在做一些事情,并且在适当的时候,它们会通知主线程必须更新 UI 的元素,并且主线程会更新 UI。我知道如何使用TThread.Synchronize(),但在某些情况下可能会发生死锁。我可以在工作线程中使用PostMessage() 并在 UI 线程中处理消息。
Delphi 中还有其他方式通知和更新 UI 线程吗?
unit FormTestSync;
interface
uses SysUtils, Classes, Forms, StdCtrls, ExtCtrls, Controls;
type
TypeThreadTest = class(TThread)
protected
procedure Execute; override;
end;
type
TForm1 = class(TForm)
timer_update: TTimer;
Label1: TLabel;
procedure timer_updateTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
m_thread: TypeThreadTest;
m_value: integer;
private
procedure Notify(value: integer);
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TypeThreadTest.Execute;
begin
while (not terminated) do begin
//do work...
form1.Notify(random(MaxInt));
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
timer_update.enabled := false;
timer_update.interval := 1;
m_thread := TypeThreadTest.Create();
end;
procedure TForm1.Notify(value: integer);
begin
//run on worker thread
//Race conditions here, I left out the synchronization for simplicity
m_value := value;
timer_update.Enabled := true;
end;
procedure TForm1.timer_updateTimer(Sender: TObject);
begin
timer_update.Enabled := false;
label1.Caption := IntToStr(m_value);
end;
end.
【问题讨论】:
-
对于
any other way,您可以在表单上为自定义消息引入消息处理程序方法,然后使用后台线程中的消息ID 对主表单句柄执行SendMessage。这就是Synchronize过去在旧版 Delphi 内部工作的方式。 -
您的代码基本上只是对
PostMessage()进行了糟糕的改造,最小延迟为 1 毫秒且副作用未知。如果您“不能相信……Microsoft 文档是 100% 准确的”,那么您为什么还要更相信有人在这里回答您的问题呢? -
如果有人说“它在我的系统上崩溃了”,那将验证 Microsoft 文档。
-
我希望在 Delphi 中编写代码来发送和处理消息会比设置计时器更麻烦,而且我的应用程序中有许多框架和控件需要更新。我希望找到在 Delphi 中是否有其他我不知道的好方法。
-
我不知道 SetTimer 的 MS 文档说它必须在 UI 线程中运行。据我所知,您可以在其他线程中创建计时器,只要在该线程中也创建了关联的窗口,并且只要您在线程中发送消息。但是,我也怀疑 UI 计时器是否可以解决您的问题。你想在你的工作线程中运行一个消息循环吗?不,我不这么认为。
标签: multithreading delphi winapi