What's the best way to wrap a synchronous code as an async Task?

半世苍凉 提交于 2019-12-07 17:55:20

问题


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 async and do return ComputeResult(). Suppress the compiler warning with pragma. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!