wait WebClient.DownloadStringTaskAsync将永远等待,但访问Result属性可以工作
本文关键字:属性 Result 工作 访问 DownloadStringTaskAsync WebClient 永远等待 wait | 更新日期: 2023-09-27 18:27:46
以下代码运行良好(在控制台上打印标记):
System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(task1.Result); // works
但当我等待任务时,它只是永远等待,任务的状态是等待激活:
System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(await task1);
Console.WriteLine("done!"); // this never gets printed
我错过了什么?
编辑:完整代码:
static void Main(string[] args)
{
DoIt();
}
static async void DoIt()
{
System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(await task1);
Console.WriteLine("done!"); // this never gets printed
}
我错过了什么?
目前,根据您调用代码的方式,我看不出该任务是如何WaitingForActivation
的。一旦DoIt
命中第一个await
,它就会将控制权交还给调用者,这就是您的Main
方法,它应该终止并关闭您的控制台。
使用Task.Result
之所以有效,是因为它在异步方法上同步阻塞,因此它等待它完成,然后您可以看到打印到控制台的结果。
实际上,您需要做的是使DoIt
成为async Task
而不是async void
,并在那里使用Task.Wait
来同步阻止,这样Main
就不会终止:
static void Main(string[] args)
{
DoItAsync().Wait();
}
static async Task DoItAsync()
{
System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(await task1);
Console.WriteLine("done!"); // this never gets printed
}
注意使用Task.Result
和Task.Wait
只是为了使控制台不终止。在任何其他环境(基于UI或ASP.NET)中,都不应该阻塞异步代码,而应该始终对异步方法执行await
。
您不是在await
或Wait()
中使用DoIt()
方法,即async
。由于Main()
不能成为async
,您唯一的选择是同步等待任务完成。
此外,await
或Wait()
异步方法不可能返回void
,因此我们必须使其返回Task
(或Task<T>
,如果方法必须返回一些值)。返回void
的异步方法的调用方无法知道它何时返回,也无法知道它是否抛出任何异常。
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Program.DoIt().Wait();
}
private static async Task DoIt()
{
System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(await task1);
Console.WriteLine("done!");
}
}