Я реализую метод интерфейса, который является асинхронным (возвращает задачу). Однако моя реализация по необходимости является синхронной. Каков наилучший способ сделать это? Есть ли встроенный способ сделать это? Вот несколько вариантов, я рассматриваю:Каков наилучший способ обернуть синхронный код как задачу async?
Вариант 1: Task.FromResult
return Task.FromResult(ComputeResult());
Это хорошо, потому что мой код работает синхронно. Недостатком является то, что если ComputeResult() терпит неудачу или отменен, мой метод бросает вместо возврата неудавшейся задачи.
Вариант 2: Task.Run
return Task.Run(() => ComputeResult());
Это распространяется отказ и аннулирование более естественно. Однако это также вводит ненужный поток-хоп.
Вариант 3: TaskCompletionSource
var tcs = new TaskCompletionSource<T>(); try { tcs.SetResult(ComputeResult()); } catch (OperationCanceledException) { tcs.SetCanceled(); } catch (Exception ex) { tcs.SetException(ex); } return tcs.Task;
Это и распространяется отказ/отмена и исключает нить-хоп, но это более многословным и сложным.
Проверьте некоторые ответы на [этот вопрос] (http://stackoverflow.com/questions/28929647/to-task-run-or-not-to-task-run). –
Только второй вариант фактически асинхронен для вызывающего. Вопрос в том, насколько плохим является блокирование вызывающего потока. Предположительно, интерфейс использует задачи, чтобы вызывающий абонент не блокировался. –
что вы подразумеваете под «нить-хоп»? –