将基于回调的异步方法转换为等待任务的最佳方法

Phi*_*ert 65 c# asynchronous task-parallel-library c#-5.0

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

例如,给定以下方法:

public void GetStringFromUrl(string url, Action<string> onCompleted);
Run Code Online (Sandbox Code Playgroud)

我知道将它包装成返回任务的方法的唯一方法是:

public Task<string> GetStringFromUrl(string url)
{
     var t = new TaskCompletionSource<string>();

     GetStringFromUrl(url, s => t.TrySetResult(s));

     return t.Task;
}
Run Code Online (Sandbox Code Playgroud)

这是实现这一目标的唯一方法吗?

有没有办法在任务本身中包含对GetStringFromUrl(url,callback)的调用(即调用本身将在任务内运行而不是同步)

svi*_*ick 32

您的代码简短,易读且高效,因此我不明白您为什么要寻找替代方案,但我无法想到任何事情.我认为你的方法是合理的.

我也不确定你为什么认为同步部分在原版中没问题,但是你想在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;
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 我并不总是控制现有的基于回调的方法,因此,如果该方法的同步部分执行的操作时间太长,我也希望选择将其移动到任务中。您的解决方案正好解决了这个问题。 (2认同)

Dre*_*rsh 6

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

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