В C# появилась конструкция async/await. Далее показан вариант как добиться подобного поведения на Delphi.
Я предпологаю, что вы знакомы с async/await. Её удобно использовать для операций, где участие процессора не требуется. Процессор только начинает операцию, а из внешнего мира приходит сообщают об её окончании. Хорошим примером может служить вызов на веб сервер. Допустим наш веб сервер умеет выполнять две операции: сложение и умножение.
Клиент хочет вычислить выражение (1+2)*(3+4). Т.к. результаты сложений независимы, их можно выполнять одновременно:
До строки "//3"(первого await) метод отрабатывает обычным образом. На await происходит выход из метода, а продолжится (до следующего await) по окончанию операции. Управление передастся механизмом сообщений или в другом потоке — настраивается в окружении. В C# это достигается возможностями компилятора. В Delphi похожего поведения на одном потоке можно достичь при помощи Fiber. Выглядеть подобный метод будет похоже:
Пример работает для Delphi 2007, XE2, XE8.
Я предпологаю, что вы знакомы с async/await. Её удобно использовать для операций, где участие процессора не требуется. Процессор только начинает операцию, а из внешнего мира приходит сообщают об её окончании. Хорошим примером может служить вызов на веб сервер. Допустим наш веб сервер умеет выполнять две операции: сложение и умножение.
async Task<int> MakeAsyncTask_Plus(int aArg1, int aArg2, int aDurationMs)
{ // эмуляция вызова на веб сервер
await Task.Delay(aDurationMs);
return aArg1 + aArg2;
}
async Task<int> MakeAsyncTask_Mult(int aArg1, int aArg2, int aDurationMs)
{ // эмуляция вызова на веб сервер
await Task.Delay(aDurationMs);
return aArg1 * aArg2;
}
Клиент хочет вычислить выражение (1+2)*(3+4). Т.к. результаты сложений независимы, их можно выполнять одновременно:
async void CalcAsync()
{
Task<int> aPlus1 = MakeAsyncTask_Plus(1, 2, 2000); // 1
Task<int> aPlus2 = MakeAsyncTask_Plus(3, 4, 2000); // 2
int aArg1 = await aPlus1; // 3
int aArg2 = await aPlus2; // 4
Task<int> aMult = MakeAsyncTask_Mult(aArg1, aArg2, 1000); // 5
int aRes = await aMult; // 6
Log(string.Format("{0} * {1} = {2}", aArg1, aArg2, aRes));
}
До строки "//3"(первого await) метод отрабатывает обычным образом. На await происходит выход из метода, а продолжится (до следующего await) по окончанию операции. Управление передастся механизмом сообщений или в другом потоке — настраивается в окружении. В C# это достигается возможностями компилятора. В Delphi похожего поведения на одном потоке можно достичь при помощи Fiber. Выглядеть подобный метод будет похоже:
procedure TCalcAsync.Execute;
var
aPlus1: TAsyncTask<Integer>;
aPlus2: TAsyncTask<Integer>;
aMult: TAsyncTask<Integer>;
aArg1, aArg2: Integer;
aRes: Integer;
begin
aPlus1 := nil;
aPlus2 := nil;
aMult := nil;
try
aPlus1 := TAsyncTask_Plus.Create(Self, 1,{+}2, 2000{ms});
aPlus2 := TAsyncTask_Plus.Create(Self, 3,{+}4, 2000{ms});
aArg1 := aPlus1.Await;
aArg2 := aPlus2.Await;
aMult := TAsyncTask_Mult.Create(Self, aArg1,{*}aArg2, 1000{ms});
aRes := aMult.Await;
Example.Log('%d * %d = %d', [aArg1, aArg2, aRes]);
finally
aMult.Free;
aPlus2.Free;
aPlus1.Free;
end;
end;
Пример работает для Delphi 2007, XE2, XE8.