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.WaitAll
및 Result
. 그들은 모두 한 번만 await
.
List<NewsContent> enresult = await lst;
핵심 문제는 필자가 블로그에서 전적으로 설명하는 교착 상태 시나리오 입니다. 요약하면, await
현재 컨텍스트를 캡처하고 다시 시작하기를 이용합니다 async
방법을. 그러나 ASP.NET은 요청 컨텍스트 내에서 한 번에 하나의 스레드 만 허용합니다. 그래서 parsing
처음이라고 그것의 돌 때까지, 그것은 실행 await
반환 한 후합니다. 그런 다음 호출하는 메소드가 차단됩니다. 블로킹으로 인해 호출하는 메서드가 해당 ASP.NET 요청 컨텍스트에서 스레드를 유지하므로 문제가있는 곳입니다.
때 나중에 await
내부 parsing
이루어집니다, 그것은 다시 시작하려고 시도 parsing
이 그 문맥에 갇혀 스레드 그리고 ASP.NET은 한 번에 하나 개의 스레드 수 있기 때문에, 그것은 할 수없는 그 ASP.NET 요청 문맥 방법을하지만. 호출 측의 메소드가 parsing
을 완료 할 때까지 대기 중입니다. parsing
parsing
은 컨텍스트가 비어있는 것을 기다리고 있습니다. 고전적인 교착 상태.