Страницы

Поиск по вопросам

воскресенье, 14 апреля 2019 г.

Создать свой Task.Run

Каким образом в c# можно сделать async получив значение во внешний метод из лямбды?
Вот тестовый пример (он нерабочий):
public async Task Test(MyClass data) { return Task.Run(() => {
MyOtherClass result = null; bool endFlag = false;
protocol.Invoke((MyOtherClass response) => // это async { endFlag = true; result = response; }, "uri/to/my/rpc", data);
for (;;) // а это уже await { Thread.Sleep(200); if (endFlag) break; }
return result;
}); }
Задача функции Test - вытащить значение response из лямбды, и вернуть его, причём, сделать это надо асинхронно, к циклу for(;;) хотелось бы перйти только когда потребуется await. Подскажите, что нужно сделать, и почему этот код студия ругает?


Ответ

Вероятно, вам надо что то вроде
public Task Test(MyClass data) { return Task.Run(async () => {
MyOtherClass result = null; bool endFlag = false;
protocol.Invoke((MyOtherClass response) => // это async { endFlag = true; result = response; }, "uri/to/my/rpc", data);
for (; ; ) // а это уже await { await Task.Delay(200); if (endFlag) break; }
return result;
}); }
Но если вызов protocol.Invoke не блокирующий, то внутренний таск нам не нужен, у нас же уже асинхронный код.
public async Task Test(MyClass data) { MyOtherClass result = null; bool endFlag = false;
protocol.Invoke((MyOtherClass response) => // это async { result = response; endFlag = true; // И лучше бы флагать о конце операции в конце метода, чтобы не возникло проблем с race condition }, "uri/to/my/rpc", data);
for (; ; ) // а это уже await { await Task.Delay(200); if (endFlag) break; }
return result; }
а вот уже совсем короткий вариант, что делает по сути то же самое
public Task Test(MyClass data) { var tcs = new TaskCompletionSource(); protocol.Invoke((MyOtherClass response) => // это async { tcs.SetResult(response); }, "uri/to/my/rpc", data); return tcs.Task; }

Комментариев нет:

Отправить комментарий