等待WebClient.DownloadStringTaskAsync永远等待,但访问Result属性工作

时间:2015-12-23 07:40:43

标签: c# asynchronous async-await task-parallel-library

以下代码正常工作(在控制台上打印标记):

System.Net.WebClient wc = new System.Net.WebClient();
var task1 = wc.DownloadStringTaskAsync("https://www.google.com.au");
Console.WriteLine(task1.Result); // works

但是,当我等待任务时,它只是等待着,任务的状态是WaitingForActivation:

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
}

2 个答案:

答案 0 :(得分:5)

  

我错过了什么?

目前,您调用代码的方式,我看不出任务是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.ResultTask.Wait只是为了使控制台不会终止。在任何其他环境(基于UI或ASP.NET)中,您不应该阻止异步代码,并且应始终{异种方法await

答案 1 :(得分:3)

您不是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!"); } } 的异步方法的调用者无法知道它何时返回以及是否抛出任何异常。

cv2.findcontours()