gpt4 book ai didi

multithreading - Delphi TTask WaitForAll 与同步

转载 作者:行者123 更新时间:2023-12-03 19:39:50 31 4
gpt4 key购买 nike

我对线程的经验有限。我想并行读取一些基本的数据库表,我需要等到所有表都读取完,程序才能合理地进行。在这方面,阻塞主线程对我来说没问题。

此代码(简化版)工作正常:

procedure ReadDBMultiThread;
var ATasks : Array of ITask;
begin
SetLength(ATasks, 3);
ATasks[0] := TTaskCreate(procedure() begin DB_ReadTable1; end);
ATasks[1] := TTaskCreate(procedure() begin DB_ReadTable2; end);
ATasks[2] := TTaskCreate(procedure() begin DB_ReadTable3; end);

ATasks[0].Start;
ATasks[1].Start;
ATasks[2].Start;

TTask.WaitForAll(ATasks);
end;

但是,假设我想更新主窗体以显示进度,即哪个数据库表已被读取(或执行任何其他必要的主线程工作)。显然,我不能使用 Synchronise(),因为这会导致 WaitForall() 的死锁,而且我不能使用 Queue(),因为它会在 WaitForAll() 完成后执行。

那么,有没有什么好的方案可以解决这种“WaitForAll vs Synchronise”的情况呢?我想,这一定是很多人遇到的情况……需要等待全部完成,但又想更新主线程……

我想到了这样的事情,用伪代码给出,替换了 WaitForAll() 语句:

repeat 
Applicaton.ProcessMessages; // or "ProcessSynchroniseMessages"
until "AllTaskCompleted"(ATasks);

这行得通吗?有更好的解决方案吗?

我是否可以编写一个自己的例程,如 ProcessMessages,但仅限于同步消息,即其他主要表单事件直到稍后才会执行?

非常感谢!

最佳答案

TThread.Synchronize()TThread.Queue() 不使用窗口消息(好吧,有一个消息“唤醒”主线程来发出信号挂起的请求,但实际同步本身不是基于消息的)。请求被放入一个全局队列中,主线程在空闲时或检测到“唤醒”消息时检查该队列。您可以通过直接调用 Classes.CheckSynchronize() 函数手动抽取同一个队列:

while not TTask.WaitForAll(ATasks, 1000) do
begin
// process any pending TThread.Synchronize() and TThread.Queue() requests
CheckSynchronize(0);
// process any pending UI paint requests, but not other messages
Application.MainForm.Update;
// anything else you need...
end;

关于multithreading - Delphi TTask WaitForAll 与同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31999429/

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