2014-11-22 115 views
0

在执行我的OTL多线程程序期间UI冻结。 使用1到16个线程进行测试,UI在程序启动后立即冻结。Delphi OTL多线程UI冻结

Parallel.ForEach(0, CalcList.Count-1) 
    .NumTasks(nMax) 
    .NoWait 
    .Execute(
    procedure(const value: integer) 
    begin 
    CalcUnit.EntrySearch(value); 
    end) 

OmniEventMonitor正确接收到所有线程消息。当所有线程都关闭时,OmniEventMonitor一次处理所有收到的消息。 如何确定是什么原因导致冻结找到解决方案。 Application.ProcessMessages和/或OmniTED.ProcessMessagesOmnitEventMonitorTaskMessage确实没有影响。

的MCVE: 上的MainForm:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Parallel.ForEach(0, 1) 
    .Execute(
    procedure(const value: integer) 
    begin 
     CalcUnit.EntrySearch; 
    end); 
end; 

在CalcUnit

procedure EntrySearch; 
var 
    I : integer ; 
begin 
    for I := 1 to 10 do begin 
    MessageBeep(MB_ICONEXCLAMATION); 
    Sleep(1000) ; 
    end; 
end; 

的MainForm的冻结,直到CalcUnit完成。

+1

你为什么要调用'ProcessMessages'?我们可以有一个MCVE? – 2014-11-22 20:57:55

+0

@DavidHeffernan感谢您的快速回复。希望通过ProcessMessages解冻主线程,(不起作用) – 2014-11-22 21:28:57

+1

“希望解冻”有时被称为“偶然编程”。了解'ProcessMessages'在您使用时会做些什么很重要。它的滥用可能导致一些微妙问题的噩梦。 ....至于你的UI为什么会冻结?这将归因于'CalcUnit.EntrySearch'方法内部的东西(或者它调用的东西等)。 – 2014-11-22 21:45:38

回答

0

应用程序UI冻结,因为它正在等待所有线程已完成。我必须在任务完成时销毁ForEach界面。在MainForm中使用OnStop方法销毁最后一个线程。看看:Incrementing Progress Bar from a ForEach Loop

{Private declarations} 
FWorker : IOmniParallelLoop<integer>; 

FWorker := Parallel.ForEach(0, CalcList.Count-1) 
.TaskConfig(Parallel.TaskConfig.OnMessage(Self)) 
.NumTasks(nMax) 
.NoWait 
.OnStop(procedure (const task: IOmniTask) 
    begin 
    task.Invoke(procedure begin 
     FWorker := nil; 
    end); 
    end); 

FWorker 
.Execute(
    procedure (const value: integer) 
    begin 
    CalcUnit.EntrySearch(value); 
    end);