问题
I am implementing an interface method that is asynchronous (returns Task). However, my implementation is by necessity synchronous. What's the best way to do this? Is there some built-in way to do this? Here are several options I'm considering:
Option 1: Task.FromResult
return Task.FromResult(ComputeResult());
This is good because my code runs synchronously. The disadvantage is that if ComputeResult() fails or is canceled my method throws instead of returning a failed task.
Option 2: Task.Run
return Task.Run(() => ComputeResult());
This propagates failure and cancellation more naturally. However, this also introduces an unnecessary thread-hop.
Option 3: TaskCompletionSource
var tcs = new TaskCompletionSource<T>(); try { tcs.SetResult(ComputeResult()); } catch (OperationCanceledException) { tcs.SetCanceled(); } catch (Exception ex) { tcs.SetException(ex); } return tcs.Task;
This both propagates failure/cancellation AND avoids the thread-hop, but it's more verbose and complex.
回答1:
Two other options you might have overlooked:
just make your method
asyncand doreturn ComputeResult(). Suppress the compiler warning withpragma. If you don't like to suppress the warning, you could do this:async Task<Result> ComputeResultAsync() { await Task.FromResult(0); return ComputeResult(); }use
Task.RunSynchronously:Task<Result> ComputeResultAsync() { var task = new Task<Result>(() => ComputeResult()); task.RunSynchronously(TaskScheduler.Default); return task; }
The latter will provide exception propagation similar to the async method. Note however, under certain conditions (like when it's too deep on the stack), RunSynchronously could still execute asynchronously.
来源:https://stackoverflow.com/questions/30851940/whats-the-best-way-to-wrap-a-synchronous-code-as-an-async-task