使用HttpClient獲取網站內容但不使用異步方法

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

我正在嘗試使用`httpclinet獲取網站內容,你可以在這裡看到

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

正如您所看到的,我使用async方法來獲取數據。其中:

var response = await http.GetByteArrayAsync(newsArchive);

但問題是當我調用我的async函數時:

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

我沒有得到任何結果。所以我決定將這個async函數轉換為普通函數,應該用這個代替什麼樣的代碼:

var response = await http.GetByteArrayAsync(newsArchive);

一般承認的答案

我想我發現你的代碼存在問題。
您沒有將NewsContent對象添加到List

foreach循環中,請將其添加到List

lstResult.Add(newsContent)

希望它能解決您的async策略問題


熱門答案

但問題是當我調用我的異步函數時:

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

是的,這是一個問題,好吧。實際上有兩個問題: Task.WaitAllResult 。他們都應該用一個await替換:

List<NewsContent> enresult = await lst;

核心問題是我在博客上完整解釋的死鎖場景 。總之, await將捕獲當前上下文並使用它來恢復async方法。但ASP.NET一次只允許其請求上下文中的一個線程。因此,當首次調用parsing時,它會執行直到它到達await然後返回。然後調用方法阻塞;這就是問題所在,因為通過阻塞,調用方法在一個ASP.NET請求上下文中保留一個線程。

稍後,當await內部parsing完成後,它會嘗試在該ASP.NET請求上下文中恢復parsing方法,但它不能,因為在該上下文中存在一個線程,並且ASP.NET一次只允許一個線程。調用方法正在等待parsing完成, parsing正在等待上下文自由。經典僵局。




許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因