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 이루어집니다, 그것은 다시 시작하려고 시도 parsing 이 그 문맥에 갇혀 스레드 그리고 ASP.NET은 한 번에 하나 개의 스레드 수 있기 때문에, 그것은 할 수없는 그 ASP.NET 요청 문맥 방법을하지만. 호출 측의 메소드가 parsing 을 완료 할 때까지 대기 중입니다. parsing parsing 은 컨텍스트가 비어있는 것을 기다리고 있습니다. 고전적인 교착 상태.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.