gpt4 book ai didi

multithreading - Delphi 线程 - 等待时卡住

转载 作者:行者123 更新时间:2023-12-03 15:42:56 35 4
gpt4 key购买 nike

我正在编写一个应用程序,需要等待目录中存在文件。我尝试了多种方法,唯一有效的解决方案是使用 Sleep/Application.ProcessMessages。

这是我尝试过的:

使用 sleep /Application.ProcessMessages:

Result := False;
for i := 0 to iTimeout do
begin
if FileExists(fileName) do
begin
updateStatus('Conversion Completed');
Result := True;
Break;
end;
updateStatus(Format('Checking for file: %d Seconds', [i]));
Application.ProcessMessages;
Sleep(1000);
end;

此方法有效,但我无法在等待时关闭应用程序。此外,使用 Sleep/Application.ProcessMessages 时存在有详细记录的问题,我宁愿避免这些问题。

使用 TThread/TEvent:

type
TMyThread = class(TThread)
private
FEventDone: TEvent;
public
constructor Create(CreateSuspended: boolean);
destructor Destroy;
procedure Execute; override;
property EventDone: TEvent read FEventDone;
end;

TformThreading = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
waitThread: TMyThread;
{ Private declarations }
public
{ Public declarations }
end;

var
formThreading: TformThreading;

implementation

{$R *.dfm}

{ TformThreading }

procedure TformThreading.Button1Click(Sender: TObject);
var
res: TWaitResult;
begin
try
waitThread.Start;
res := waitThread.EventDone.WaitFor(INFINITE);
case res of
wrSignaled: ShowMessage('wrSignaled');
wrTimeout: ShowMessage('wrTimeout');
wrAbandoned: ShowMessage('wrAbandoned');
wrError: ShowMessage('wrError');
wrIOCompletion: ShowMessage('wrIOCompletion');
end;
except
on E: Exception do
begin
ShowMessage(E.Message);
end;
end;
end;

procedure TformThreading.FormCreate(Sender: TObject);
begin
waitThread := TMyThread.Create(true);
end;

procedure TformThreading.FormDestroy(Sender: TObject);
begin
waitThread.Free;
end;

{ TMyThread }

constructor TMyThread.Create(CreateSuspended: boolean);
begin
inherited Create(CreateSuspended);
FEventDone := TEvent.Create;
end;

destructor TMyThread.Destroy;
begin
FEventDone.Free;
end;

procedure TMyThread.Execute;
begin
for i := 0 to iTimeout do
begin
if FileExists(fileName) do
begin
FEventDone.SetEvent;
Break;
end;
Application.ProcessMessages;
Sleep(1000);
end;
end;

我似乎无法让它在等待时不卡住我的主线程,但如果我能解决卡住问题,这似乎是正确的方法。

解决问题的最佳方法是什么?

最佳答案

I can't seem to get this to not freeze my main thread while it is waiting.

当您等待一个对象时,该线程会阻塞,直到该对象收到信号为止。因此,当您的主线程等待事件时,它会被阻止。您观察到的行为完全符合预期。

查看线程的代码,它会循环直到满足条件,发出事件信号,然后终止。换句话说,这次事件没有任何意义。您可以将其删除并等待线程。

现在,如果您这样做,您的代码将执行以下操作:

  1. 创建一个线程并开始执行。
  2. 等待该线程完成,阻塞主线程。
  3. 线程完成后继续执行。

因此,就目前情况而言,您的线程没有取得任何成果。你也可以在主线程中执行它的代码。你又回到了起点。

你需要不同的心态。 GUI 程序的 UI 是异步的。你需要遵循这个模式。不要在主线程中等待。相反,请务必使用单独的线程,但在完成时让该线程向主线程发出信号。

最简单的方法是为线程实现一个 OnTerminate 事件处理程序。当线程完成其工作时,它将触发。事件处理程序将在主线程中执行。

更一般地,您可以使用 SynchronizeQueue 向主线程发出事件信号,但在您的情况下,处理终止事件可以满足您的需求。

现在到线程正文。您的方法基于轮询,并带有 sleep 。这会起作用,但不是很漂亮。 ReadDirectoryChangesW 函数是系统提供的机制,供您接收文件系统更改的通知。这将是一种更优雅的方法。

我的建议是首先使用当前的轮询方法解决阻塞问题。一旦明确重构即可使用ReadDirectoryChangesW

关于multithreading - Delphi 线程 - 等待时卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44467221/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com