Лучший способ конвертировать метод async на основе обратного вызова в ожидаемую задачу
Каким будет лучший способ конвертировать/переносить "классический" асинхронный метод, который использует обратный вызов для чего-то, что возвращает (ожидаемую) задачу?
Например, с учетом следующего метода:
public void GetStringFromUrl(string url, Action<string> onCompleted);
Единственный способ, которым я знаю, включить это в метод, возвращающий задачу:
public Task<string> GetStringFromUrl(string url)
{
var t = new TaskCompletionSource<string>();
GetStringFromUrl(url, s => t.TrySetResult(s));
return t.Task;
}
Это единственный способ добиться этого?
И есть ли способ обернуть вызов GetStringFromUrl (url, callback) в самой задаче (т.е. сам вызов будет выполняться внутри задачи вместо синхронного)
Ответы
Ответ 1
Ваш код короткий, читабельный и эффективный, поэтому я не понимаю, почему вы ищете альтернативы, но я ничего не могу придумать. Я думаю, что ваш подход разумный.
Я также не уверен, почему вы считаете, что синхронная часть в порядке, но вы хотите избежать ее в Task
. Если вы считаете, что синхронная часть может занять слишком много времени, исправьте ее для обеих версий метода.
Но если вы хотите запустить его асинхронно (т.е. на ThreadPool
) только в версии Task
, вы можете использовать Task.Run()
:
public Task<string> GetStringFromUrl(string url)
{
return Task.Run(() =>
{
var t = new TaskCompletionSource<string>();
GetStringFromUrl(url, s => t.TrySetResult(s));
return t.Task;
});
}
Ответ 2
Предполагаемая реализация прекрасно подходит для этого, если обратный вызов только когда-либо обрабатывает успешные ситуации. Что происходит, если исключение происходит в рамках async-подтекстов реализации GetStringFromUrl? Нет никакого реального способа для них распространять это на обратный вызов Action... они просто проглатывают его и возвращают вам нуль или что-то еще?
Единственное, что я хотел бы порекомендовать, это использовать следующее соглашение об именах таких методов async с суффиксом XXXAsync.