Асинхронные задачи C# ждут бесконечно

Я пытаюсь использовать функциональность, предоставляемую "async" & "await" для асинхронной загрузки содержимого веб-страницы, и у меня есть проблемы, когда задачи ждут завершения навсегда. Не могли бы вы сообщить мне, что не так со следующим фрагментом кода?

protected void Page_Load(object sender, EventArgs e)
{
    var websites = new string[] {"http://www.cnn.com","http://www.foxnews.com"};
    var tasks = websites.Select(GenerateSomeContent).ToList();

    //I don't want to use 'await Tasks.WhenAll(tasks)' as I need to block the
    //page load until the all the webpage contents are downloaded
    Task.WhenAll(tasks).Wait();

    //This line is never hit on debugging
    var somevalue = "Complete";
}

static async Task<Results> GenerateSomeContent(string url)
{
    var client = new HttpClient();
    var response = await client.GetAsync(url); //Await for response
    var content = await response.Content.ReadAsStringAsync();
    var output = new Results {Content = content};
    return output;
}

//Sample class to hold results
public class Results
{
    public string Content;
}

2 ответов


во-первых, убедитесь, что вы работаете на .NET 4.5, а не .NET 4.0. ASP.NET было сделано async - aware в .NET 4.5.

тогда правильное решение -await результат Task.WhenAll:

var tasks = websites.Select(GenerateSomeContent);
await Task.WhenAll(tasks);

ASP.NET конвейер (только в .NET 4.5) обнаружит, что ваш код awaiting и остановит этот запрос до Page_Load выполняется до завершения.

синхронная блокировка задачи с помощью Wait в этой ситуации вызывает тупик как я объясняю в моем блог.


+1 Стивен Клири. Просто узнал, что вам нужно иметь асинхронный тип перед void с Page_Load, как показано ниже:

protected async void Page_Load(object sender, EventArgs e)
{
   var tasks = websites.Select(GenerateSomeContent);
   await Task.WhenAll(tasks);
}

а затем в вашем файле с кодом (в случае asp.net web form app) также должен иметь атрибут Async= "true".

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Async="true" Inherits="EmptyWebForm._default" %>

надеюсь, это поможет посетителям.