为什么OmniThreadLibrary的ForEach阻塞主线程? [英] Why is OmniThreadLibrary's ForEach blocking main thread?
问题描述
使用OmniThreadLibrary和Delphi XE4,我希望运行多个在后台处理数据的线程,增加了我现有代码的速度。
Using the OmniThreadLibrary and Delphi XE4, I am hoping to run multiple threads that process data in the background, adding speed increases to my already existing code.
当调用下面的过程中,应用程序GUI停止处理任何输入,直到所有线程完成。我的理解是,使用 .NoWait
应该允许程序退出,即使线程正在运行。
When calling the procedure below, the Application GUI stops processing any input until all of the threads have completed. My understanding is that using .NoWait
should allow the procedure to exit even when the threads are running.
procedure Test(input: TStringList; output: TList<TMaintFore>);
var
outQueue: IOmniBlockingCollection;
transaction: TOmniValue;
begin
outQueue := TOmniBlockingCollection.Create;
Parallel.ForEach(0, input.Count - 1)
.NoWait
.Into(outQueue)
.Execute(
procedure(const value: integer; var result: TOmniValue)
begin
result := TMaintFore.Create(input[value]);
end
);
end;
我对ForEach循环的理解不正确,提示我应该使用替代方法来实现后台处理?对于正确使用OmniThreadLibrary的任何建议都是值得赞赏的。
Is my understanding of the ForEach loop incorrect, suggesting I should use an alternate method to achieve background processing? Any suggestions on the correct use of the OmniThreadLibrary is appreciated.
推荐答案
你必须存储从Parallel.ForEach返回的界面一个全局(form etc)变量,只有当ForEach完成执行时才会销毁它。
You have to store the interface returned from the Parallel.ForEach in a global (form etc) variable and destroy it only when the ForEach finishes execution.
在您的示例中,ForEach的结果存储在临时变量中,测试程序退出。 ForEach析构函数等待所有任务完成并阻止您的程序。
In your example, the result of ForEach is stored in a temporary variable which is destroyed when the Test procedure exits. The ForEach destructor waits for all tasks to complete and that blocks your program.
在任务完成时销毁foreach接口的最安全(但绝对不明显)的方式是使用OnStop方法,并从其中将命令排队到主线程。
The safest (but admittedly non-obvious) way to destroy the foreach interface on task completion is to use the OnStop method and from it queue a command to the main thread.
var
loop: IOmniParallelLoop<integer>;
loop := Parallel.ForEach(1, N).NoWait;
loop.OnStop(
procedure (const task: IOmniTask)
begin
task.Invoke(
procedure
begin
// do anything
loop := nil;
end);
end);
loop.Execute(
procedure (const value: integer)
begin
...
end);
这被记录在维基。
这篇关于为什么OmniThreadLibrary的ForEach阻塞主线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!