Task <int>如何成为一个int?

Fre*_*man 101 .net c# asynchronous c#-5.0 .net-4.5

我们有这个方法:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}
Run Code Online (Sandbox Code Playgroud)

之间是否隐式转换发生Task<int>int?如果没有,那么发生了什么?它是如何实现的?

Jon*_*eet 151

在Task <>和int之间是否发生了隐式转换?

不.这只是如何async/ await工作的一部分.

声明为的任何方法async必须具有以下返回类型:

  • void (尽可能避免)
  • Task (除完成/失败通知外没有结果)
  • Task<T>(对于T异步方式的类型的逻辑结果)

编译器执行所有适当的包装.关键是你异步返回urlContents.Length- 你不能让方法返回int,因为实际的方法将在它到达第一个await尚未完成的表达式时返回.因此,它返回一个Task<int>在异步方法本身完成时将完成的.

请注意,await则正好相反-它解开Task<T>到一个T值,这是此行是如何工作的:

string urlContents = await getStringTask;
Run Code Online (Sandbox Code Playgroud)

...但当然它是异步打开它,而只是使用Result会阻塞,直到任务完成.(await可以解开实现等待模式的其他类型,但是Task<T>最常用的是.)

这种双重包装/解包是允许异步可组合的原因.例如,我可以编写另一个异步方法来调用你的结果并将结果加倍:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}
Run Code Online (Sandbox Code Playgroud)

(或者return await AccessTheWebAsync() * 2;当然.)

  • +1一如既往的好答案.为什么你这么快写作呢?! (8认同)
  • +1:刚开始研究`async` /`await`,我发现这非常不直观.IMO,在`return`上应该有一个关键字或者类似的东西,以便明确这一点,例如`返回异步结果;`(与`await result`相同的方式'从`Tast <T>解开`T` `). (8认同)
  • @dav_i:*assignment* 没有意义,但其余的都有意义。在某些情况下,整个语句都有意义——尽管它可能没有用。鉴于该方法已经声明为 `async`,我认为这就足够了。 (3认同)
  • 可以提供有关如何在引擎盖下工作的任何细节,只是好奇. (2认同)
  • @JonSkeet但没有`await`就没有意义 - 用`T foo = someTaskT;`你得到"不能隐式地将类型`Task <T>`转换为`T`" - 就像我争辩一样为反向设置关键字更有意义(包装在`Task <T>`中).我全都是为了消除绒毛,但在这种情况下,我认为它在`async`方法中提供了一种不必要的混淆.(显然,这一点是没有意义的,因为已经说过/编码的权力!) (2认同)

Ani*_*rma 13

不需要将Task转换为int.只需使用任务结果.

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}
Run Code Online (Sandbox Code Playgroud)

如果可用,它将返回值,否则返回0.

  • 这不是我问的. (15认同)
  • 这不回答这个问题.但更重要的是,**这是非常糟糕的建议**.你应该*从不*使用`结果`; 它会导致死锁!考虑一下这个工作流程:(1)写一个说"割草坪"的笔记.(2)等待草坪被修剪(3)吃三明治,(4)做任何在笔记上说的话."通过这个工作流程,你从不吃三明治或割草坪,因为第2步是*同步等待你将要做的事*将来*.但这就是你在这里描述的工作流程. (8认同)
  • 等待是指在等待结果时执行某项操作,并且该操作可能包括进行工作以计算结果。但是同步等待在您等待时什么也没做,这意味着您可能无法完成工作。 (2认同)