Ottieni il contenuto del sito web utilizzando HttpClient ma senza metodo asincrono

asp.net-mvc asynchronous c# html-agility-pack http

Domanda

Sto cercando di recuperare il contenuto del sito web usando `httpclinet come puoi vedere qui

public async Task<List<NewsContent>> parsing(string newsArchive)
{
    List<NewsContent> lstResult=new List<NewsContent>();
    HttpClient http = new HttpClient();
    var response = await http.GetByteArrayAsync(newsArchive);
    String source = Encoding.GetEncoding("utf-8").GetString(response, 0, response.Length - 1);
    source = WebUtility.HtmlDecode(source);
    HtmlDocument resultat = new HtmlDocument();
    resultat.LoadHtml(source);

    List<HtmlNode> toftitle = resultat.DocumentNode.Descendants().Where
    (x => (x.Name == "div" && x.Attributes["class"] != null && x.Attributes["class"].Value.Contains("news_list"))).ToList();
    var li = toftitle[0].Descendants().Where
    (x => (x.Name == "div" && x.Attributes["class"] != null && x.Attributes["class"].Value=="news_item")).ToList();

    foreach (var item in li)
    {
        NewsContent newsContent = new NewsContent();
        newsContent.Url = item.Descendants("a").ToList()[0].GetAttributeValue("href", null);
        newsContent.Img = item.Descendants("img").ToList()[0].GetAttributeValue("src", null);
        newsContent.Title = item.Descendants("h2").ToList()[0].InnerText;

        //finding main news content
        var response1 = await http.GetByteArrayAsync("http://www.nsfund.ir/news" + newsContent.Url);
        String source1 = Encoding.GetEncoding("utf-8").GetString(response1, 0, response1.Length - 1);
        source1 = WebUtility.HtmlDecode(source1);
        HtmlDocument resultat1 = new HtmlDocument();
        resultat1.LoadHtml(source1);
        newsContent.Content = resultat1.DocumentNode.SelectSingleNode("//div[@class='news_content_container']").InnerText;


    }
    return  lstResult;
}

Come puoi vedere ho usato il metodo async per ottenere i dati .qui:

var response = await http.GetByteArrayAsync(newsArchive);

Ma il problema è quando chiamo la mia funzione async :

News newagent = new News();
Task<List<NewsContent>> lst = newagent.parsing("http://www.nsfund.ir");
Task.WaitAll(lst);
List<NewsContent> enresult = lst.Result;

Non ho alcun risultato. Così ho deciso di convertire questa funzione async in una funzione normale, che tipo di codice dovrebbe essere sostituito con questo:

var response = await http.GetByteArrayAsync(newsArchive);

Risposta accettata

Credo di aver trovato il problema con il tuo codice.
Non stai aggiungendo l'oggetto NewsContent al tuo List .

nel ciclo foreach , aggiungilo alla List

lstResult.Add(newsContent)

Spero che risolva il problema con la tua strategia async


Risposta popolare

Ma il problema è quando chiamo la mia funzione asincrona:

Task.WaitAll(lst);
List<NewsContent> enresult = lst.Result;

Sì, è un problema, va bene. Due problemi, in realtà: Task.WaitAll e Result . Dovrebbero essere entrambi sostituiti con una singola await :

List<NewsContent> enresult = await lst;

Il problema principale è uno scenario di stallo che spiego per intero sul mio blog. In sintesi, await acquisirà il contesto corrente e lo utilizzerà per riprendere il metodo async . Ma ASP.NET consente solo un thread all'interno del suo contesto di richiesta alla volta. Quindi, quando l' parsing viene prima chiamata, viene eseguita fino a quando non raggiunge l' await e quindi ritorna. Il metodo di chiamata quindi blocca; questo è dove il problema è, perché bloccando, il metodo chiamante è mantenere un thread in quel contesto di richiesta ASP.NET.

Successivamente, quando viene eseguita l' await all'interno parsing , tenta di riprendere il metodo di parsing in quel contesto di richiesta ASP.NET ma non è possibile, perché c'è un thread bloccato in quel contesto e ASP.NET consente solo un thread alla volta. Il metodo di chiamata è in attesa di parsing per completare, e parsing è in attesa per il contesto di essere liberi. Stallo classico.



Related

Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow