Надеюсь, простой.Я использую цикл OTL Parallel.For для обработки большого количества данных.Объем данных может измениться, и если их много (это занимает более 2 секунд), Windows мерцает в форме заявки и дает временный статус «не отвечает» в строке заголовка.
Чтобы обойти это, я подумалЯ мог бы поместить процедуру с циклом Parallel.For в асинхронный вызов OTL, например
done:=false;
Async(ProcedureThatDoesParallelFor).Await(
procedure begin
done:=true;
end);
repeat application.processmessages until done=true;
. Это работает (или, кажется, работает), но может привести к тому, что программа просто прерывается / завершается без каких-либо сообщений об ошибках.Кажется, что это вызывает проблему «молчаливого прерывания», когда цикл Parallel.For выполняется очень быстро.
Если я отмечу приведенный выше код и возьму вызов MethodThatDoesParallelFor вне него, приложение будет работать нормально без неожиданного выхода,поэтому я предполагаю, что это должен быть асинхронный вызов, вызывающий проблему.Или комбинация Parallel.For в Async?
Является ли использование Async лучшим способом для запуска другой процедуры и ожидания ее завершения?Есть ли лучший OTL способ сделать это?
Спасибо за любые идеи или решения.
Вот самый простой пример, показывающий ошибку сбоя.Одиночная форма с памяткой и кнопкой.Нажмите кнопку, и программа будет зависать вокруг итерации 300.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,OtlParallel,OtlTaskControl;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure AsyncParallelFor;
var iterations:integer;
blah:integer;
begin
iterations:=10;
//for iter:=0 to limit-1 do
Parallel.For(0,iterations-1).Execute(procedure(iter:integer)
var x,y:integer;
begin
for y:=0 to 50 do
begin
for x:=0 to 50 do
begin
blah:=x+y;
end;
end;
end);
end;
procedure AsyncProcedure;
var done:boolean;
begin
done:=false;
Parallel.Async(
procedure
begin
//executed in background thread
AsyncParallelFor;
end,
Parallel.TaskConfig.OnTerminated(
procedure (const task: IOmniTaskControl)
begin
//executed in main thread after the async has finished
done:=true;
end
)
);
//this point is reached immediately after the call to Async
//the repeat loop waits until the Async is finished being signalled via done variable
repeat
application.processmessages;
until done=true;
end;
procedure TForm1.Button1Click(Sender: TObject);
var iters:integer;
begin
iters:=0;
repeat
memo1.lines.add('Iteration '+inttostr(iters)+'...');
memo1.lines.add('Before Async');
application.processmessages;
AsyncProcedure;
memo1.lines.add('After Async');
application.processmessages;
inc(iters);
until 1>2;
end;
end.
AsyncParallelFor показывает основные вложенные циклы.Это просто простое дополнение для демонстрации проблемы.
AsyncProcedure выполняет вызов OTL Async и ожидает возврата.
У меня много непараллельного кода до и после вызова AsyncProcedureчто нужно дождаться окончания цикла параллельного. for.
Если я изменю щелчок кнопки, чтобы вызвать AsynParallelFor напрямую без Async, то зависание не будет.