【问题标题】:Can I make a method that returns Task<T> to run synchronously?我可以创建一个返回 Task<T> 的方法以同步运行吗?
【发布时间】:2015-05-20 22:36:49
【问题描述】:

考虑这个相当简单的方法:

private bool ValidateKey(HttpRequestMessage message)
{

}

上述方法调用如下

if (!ValidateKey(request))
{
//do something
}

现在我想在 ValidateKey 中调用一个返回 Task 的方法。我们假设它是 HttpRequestMessage 中的 ReadAsStringAsync 方法:

message.Content.ReadAsStringAsync();

既然这个方法可以异步运行,我最好这样称呼它:

string output = await message.Content.ReadAsStringAsync();

但这将要求我更改我的方法签名以包括异步和返回类型为 Task,然后调用者也...无限。

可以同步调用 ReadAsStringAsync,即我愿意让 ValidateKey 等到 ReadAsStringAsync 完成。这将省去我为了迎合这一方法而更改代码的麻烦。

【问题讨论】:

标签: c# async-await


【解决方案1】:

初始(错误)答案部分(我将其留在这里以供将来参考)

你可以使用Task.RunSynchronously让任务同步运行,虽然技术上它仍然是异步的,但是你阻塞了当前的执行,所以它是同步的:

Task<string> t = message.Content.ReadAsStringAsync();

t.RunSynchronously();

string result = t.Result;

这仅在您的方法返回 new Task 时才有效(因为您只能调用 Run 一次),因此当方法被声明为 async 时这将不起作用...

解决方案

只需以同步方式等待结果。这将阻止执行。

Task<string> t = message.Content.ReadAsStringAsync();

string result = t.Result;

【讨论】:

    【解决方案2】:

    ReadAsStringAsync() 返回一个Task&lt;string&gt;,因此,为了等待(阻塞)结果,您只需要获取Result 属性:

    var task = message.Content.ReadAsStringAsync();
    string output = task.Result;
    

    【讨论】:

      【解决方案3】:

      没有。如果操作是固有异步,则您无法同步运行它。但是,您可以阻塞线程并等待它完成。

      我强烈建议不要这样做。您应该一直进行操作async,或者根本不使用异步操作。

      您也可以使用 Stephen Cleary 的AsyncContext

      string output = AsyncContext.Run(() => message.Content.ReadAsStringAsync());
      

      如果您仍打算阻塞,请使用GetAwaiter().GetResult(),因为它在异常处理方面更接近await 的作用:

      string output = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
      

      【讨论】:

      • 为什么?仅仅因为一种方法,我的整个调用堆栈签名都必须修改。
      • @BobbyAlexander 我知道,这是值得的。否则,您将限制可扩展性和响应能力,并有死锁的风险。
      • 可能,但我相信这是可以根据具体情况考虑的。例如:在上面的例子中,比如说,你总是知道消息内容总是一个 20 字符的字符串。
      • @BobbyAlexander 最后,由您决定。我刚刚给了你制作它所需的所有信息。如果您要阻止不要使用Result,请使用GetAwaiter().GetResult()
      • @batmaci 总体而言,它阻塞了线程。它是同步的而不是异步的。与同样阻塞线程的GetAwaiter().GetResult() 相比,Result 抛出一个AggregateException 而不是实际的异常。
      猜你喜欢
      • 2011-07-02
      • 1970-01-01
      相关资源
      最近更新 更多