C# 我可以创建一个返回任务的方法吗<;T>;同步运行?

C# 我可以创建一个返回任务的方法吗<;T>;同步运行?,c#,async-await,C#,Async Await,考虑一下这个相当简单的方法: private bool ValidateKey(HttpRequestMessage message) { } 上面的方法调用如下 if (!ValidateKey(request)) { //do something } 现在我想在ValidateKey中调用一个方法,该方法返回Task。让我们假设它是HttpRequestMessage中的ReadAsStringAsync方法: message.Content.ReadAsStringAsync();

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

private bool ValidateKey(HttpRequestMessage message)
{

}
上面的方法调用如下

if (!ValidateKey(request))
{
//do something
}
现在我想在ValidateKey中调用一个方法,该方法返回Task。让我们假设它是HttpRequestMessage中的ReadAsStringAsync方法:

message.Content.ReadAsStringAsync();
现在,由于此方法可以异步运行,因此理想情况下,我应该这样调用它:

string output = await message.Content.ReadAsStringAsync();
但这将要求我更改我的方法签名,以包括async和Task的返回类型,然后也包括调用者。。。无限的

可以同步调用ReadAsStringAsync,也就是说,我愿意让ValidateKey等待ReadAsStringAsync完成。这将省去我为适应这一方法而更改代码的麻烦。

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

您可以使用使任务同步运行,虽然从技术上讲它仍然是异步的,但您阻止了当前的执行,因此它有点同步:

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

t.RunSynchronously();

string result = t.Result;
ReadAsStringAsync()
返回一个
任务
因此,为了等待(阻塞)结果,您只需要获取
result
属性:

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

否。如果操作本质上是异步的,则不能同步运行。但是,您可以阻止线程并等待它完成

不过,我强烈建议不要这样做。您应该始终使操作
异步
,或者根本不用使用异步操作

Stephen Cleary还可以使用:

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
抛出一个
aggregateeexception
,而不是实际的异常。正如下面两个答案中所述,调用Result属性将导致线程阻塞,直到获得异步方法的返回值为止。然而,我发现了斯蒂芬·克利里(Stephen Cleary)的一个非常好的答案,描述了为什么这可能不是一个好主意。可能重复的
string output = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();