如何创建现有同步方法的异步重载?

How do I create an async overload of an existing synchronous method?

我有几个库目前不支持 async/await,我正在尝试更新它们。对于可以调用现有异步代码的方法(例如使用 File.ReadAllLinesAsync 而不是 File.ReadAllLines),创建异步重载非常容易。但是,对于不调用其他具有异步能力的代码的方法,重载就不是那么容易了。

举个例子,假设我有一个方法如下:

public ResultType DoLotsOfStuff(string p1, string p2)
{
   ResultType result = new ResultType();
   // Do Lots of stuff here.
   // update result

   return result;
}

我想创建此方法的异步重载,但不想复制其中的所有代码。所以该方法简单地开始:

public Task<ResultType> DoLotsOfStuffAsync(string p1, string p2)

问题变成了我在新重载中如何调用原始方法?

我看到了几个可能的答案,但不确定其中是否有一个是好的,也不确定在什么情况下哪个是最好的。到目前为止,我已经看到了这些:

方法一:使用Task.Yield

public Task<ResultType> DoLotsOfStuffAsync(string p1, string p2)
{
   Task.Yield();
   return DoLotsOfStuff(p1, p2);
}

方法二:使用Task.Run

public Task<ResultType> DoLotsOfStuffAsync(string p1, string p2)
{
   return await Task.Run(() => DoLotsOfStuff(p1, p2));
}

方法三:使用Task.FromResult

public Task<ResultType> DoLotsOfStuffAsync(string p1, string p2)
{
   ResultType result = DoLotsOfStuff(p1, p2);
   return await Task.FromResult(result);
}

这三个都编译得很好,所以我不确定该用哪个。它们等价吗?如果不是,分别使用的后果是什么?

作为背景知识,这些库可用于各种应用程序,包括 ASP.Net 核心网络应用程序、.Net Core 控制台应用程序和可能的 .Net Core UI 应用程序。我已经做了几个小时的互联网搜索并找到了所有这些方法,只是没有什么时候可以使用。

谢谢!

这三种方法都是伪异步。如果您不打算提供真正的异步实现(通过等待 naturally/actually 像 IO 这样的异步操作),那么根本不要提供这些重载。

我强烈推荐阅读 Task.Run Etiquette,Alexander Petrov 已经发表了评论。