136

我们有这个方法:

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;
}

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

4

2 回答 2

204

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

没有。这只是async/await工作方式的一部分。

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

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

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

请注意,await相反 - 它将a 解包Task<T>一个T值,这就是该行的工作方式:

string urlContents = await getStringTask;

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

这种双重包装/展开使异步变得如此可组合。例如,我可以编写另一个异步方法来调用你的方法并将结果加倍:

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

(或者只是return await AccessTheWebAsync() * 2;当然。)

于 2012-10-31T13:32:07.840 回答
21

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

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

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

于 2016-07-16T04:36:56.147 回答