将使用回调的“经典”异步方法转换/包装为返回(等待)任务的东西的最佳方法是什么?
例如,给定以下方法:
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) 的调用(即调用本身将在任务内部运行而不是同步运行)
BeginXxx()
和 EndXxx()
对。另外,您为什么要寻找其他方法来做到这一点?你希望得到什么?
TrySetResult
而不是 SetResult
吗?
您的代码简短,可读且高效,因此我不明白您为什么要寻找替代方案,但我想不出任何东西。我认为你的方法是合理的。
我也不确定为什么您认为原始版本中的同步部分没问题,但您想在基于 Task
的版本中避免它。如果您认为同步部分可能需要太长时间,请为该方法的两个版本修复它。
但如果您只想在 Task
版本中异步运行它(即在 ThreadPool
上),您可以使用 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;
});
}
假设回调只处理成功的情况,您假设的实现对此非常好。如果在 GetStringFromUrl 实现的异步基础中发生异常,当前会发生什么?他们没有真正的方法将其传播到 Action 回调......他们是否只是吞下它并返回 null 或其他东西?
我唯一推荐的是遵循使用 XXXAsync 后缀命名此类异步方法的新约定。