88

将使用回调的“经典”异步方法转换/包装为返回(等待)任务的东西的最佳方法是什么?

例如,给定以下方法:

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) 的调用(即调用本身将在任务内部运行而不是同步运行)

4

2 回答 2

45

您的代码简短,可读且高效,因此我不明白您为什么要寻找替代方案,但我想不出任何东西。我认为你的方法是合理的。

我也不确定为什么您认为原始版本中的同步部分是可以的,但您想在Task基于 - 的版本中避免它。如果您认为同步部分可能需要太长时间,请为该方法的两个版本修复它。

但是,如果您只想在版本中异步运行它(即在 上ThreadPoolTask,您可以使用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;
    });
}
于 2012-08-09T12:23:25.850 回答
6

假设回调只处理成功的情况,您假设的实现对此非常好。如果在 GetStringFromUrl 实现的异步基础中发生异常,当前会发生什么?他们没有真正的方法将其传播到 Action 回调......他们是否只是吞下它并返回 null 或其他东西?

我唯一推荐的是遵循使用 XXXAsync 后缀命名此类异步方法的新约定。

于 2012-08-09T22:20:48.123 回答