Должен добавить, что я не являюсь опытным задавателем вопросов в Stackoverflow, поэтому буду рад отзывам о том, почему мой вопрос не подходит сюда.
Является ли ожидание TaskCompletitionSource плохой вещью при переносе неасинхронного вызова?
Вот мой вариант использования:
У меня есть класс обработчика, который вызывает функцию обратного вызова Func<T, Task>
при возникновении события. Обработчик вызывается извне моего приложения и уведомляет мой пользовательский интерфейс. Есть два метода A и B, которые используются в качестве обратного вызова. A, где вызывается асинхронный HTTP-клиент, и B, где я выполняю вычисления. В обоих случаях вызов await разморозит пользовательский интерфейс, а затем обновятся свойства.
A:
public async Task A(){
result = await CallHttpClient(...) // unfreeze UI
// ... copy image bytes and update UI (long running not async)
// release bytes in calling method
}
B:
public async Task B(){
var tcs = new TaskCompletionSource<bool>();
await tcs.Task; // unfreeze UI
// ... copy image bytes and update UI (long running not async)
tcs.SetResult(true); // release bytes in calling method
}
Мой вопрос здесь, это плохая практика использовать TaskCompletionSource для переноса не асинхронного вызова?
В документации указано следующее.
Если вы хотите создать оболочку задачи для существующей асинхронной операции или события, используйте TaskCompletionSource. https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming
Другая возможность — вызвать Task.Run(), но мне это кажется еще хуже. Неиспользование Async приведет к зависанию пользовательского интерфейса, что на самом деле не то, что мне нужно, хотя это может быть самое чистое решение.
-------> Обновить
Как утверждают другие, Task.Run() здесь прекрасно работает.
Я должен отметить, что мой B: выглядит иначе B:
public async Task B(...){
var tcs = new TaskCompletionSource<bool>();
// ... duplicate bytes
tcs.SetResult(true); // release bytes in calling method
await tcs.Task; // unfreeze UI
// ... copy image bytes and update UI (long running not async)
}
Найдите лучший вариант с Task.Run() ниже.
Я также должен отметить, что когда метод выходит, байты (не показанные в примере) освобождаются.
await
илиTask.Run
? - person Panagiotis Kanavos   schedule 31.01.2020await
доtcs.SetResult
? Он застрянет наawait
. - person GSerg   schedule 31.01.2020await tcs.Task;
ничего не размораживает.await
не размораживается, он ожидает завершения уже асинхронной операции без блокировки потока. Если эта операция (или tcs в данном случае) никогда не завершится,await
не вернется - person Panagiotis Kanavos   schedule 31.01.2020await httpClient.GetStringAsync()
GetStringAsync()
является асинхронной операцией, аawait
ожидает ее, не блокируя поток, возобновляя выполнение в этом потоке после его завершения. Неawait
делаетGetStringAsync
асинхронным методом - person Panagiotis Kanavos   schedule 31.01.2020