Лучший способ преобразовать асинхронный метод на основе обратного вызова в ожидаемую задачу
Каков был бы лучший способ преобразовать / обернуть "классический" асинхронный метод, который использует обратный вызов чего-то, что возвращает (ожидаемое) задание?
Например, дан следующий метод:
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) в самой задаче (т.е. сам вызов будет выполняться внутри задачи, а не синхронно)
2 ответа
Ваш код короткий, читаемый и эффективный, поэтому я не понимаю, почему вы ищете альтернативы, но я ничего не могу придумать. Я думаю, что ваш подход разумен.
Я также не уверен, почему вы думаете, что синхронная часть хорошо в оригинальной версии, но вы хотите избежать этого в 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;
});
}
Ваша предполагаемая реализация вполне подходит для этого, если предположить, что обратный вызов только когда-либо обрабатывает успешные ситуации. Что в настоящее время происходит, если исключение происходит внутри асинхронных основ реализации GetStringFromUrl? У них нет реального способа передать это обратному вызову Action... они просто проглатывают его и возвращают ноль или что-то еще?
Единственное, что я бы порекомендовал, - это использовать следующее соглашение о присвоении имен асинхронным методам с суффиксом XXXAsync.