2013-06-19 2 views
1

WebAPI ASP.NET 솔루션이 있습니다. (십초 각) 나는 3 개 작업의 결과를 얻을 필요가 전화에서작업 대기 중일 때 IIS가 실패 함

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 

:

Task<Cat> catAsync = GetCatAsync(); 
Task<Dog> dogAsync = GetDogAsync(); 
Task<Pig> pigAsync = GetPigAsync(); 

await Task.WhenAll(catAsync , dogAsync , pigAsync); 

cat= catAsync.Result; 
dog= dogAsync.Result; 
pig= pigAsync.Result; 

내가 한 번 호출 할 수 있지만, 후속 호출을 내가 가진의 Web.config 설정 이것에 스레드에서 죽는 것, 고양이와 개가 실행될 수 있지만 돼지는 기화하는 것 같습니다.

The thread '<No Name>' (0x2f60) has exited with code 0 (0x0). 
The thread '<No Name>' (0x974) has exited with code 0 (0x0). 
The thread '<No Name>' (0x1ea8) has exited with code 0 (0x0). 

내 작업은 다음과 같이 : 분 정도 후에 이러한 표시 시작

private async Task<Cat> CatAsync() 
    { 
     await Task.Run(() => 
      { 
       //Use WCF to get some data from a service 
      }); 

     return cat; 
    } 

이의 나를 다시 한 번 사이트 운영을 할 수 iisreset을 실행합니다.

* 편집

은 그 아래의 솔루션이 작업이 장시간 실행이 경우, IIS는 모든 스레드를 죽이고 요청을 종료 할 수 있습니다 파나지오티스 Kanavos에 의해

+0

나는 당신의 제목을 편집했습니다. "[제목에"태그 "가 포함되어 있어야합니까?] (http://meta.stackexchange.com/questions/19190/)"합의가 "아니오, 그렇지 않아야합니다"로 표시되어야합니다. –

+0

"스레드 X가 코드 0 (0x0)으로 종료되었습니다."메시지는 오류가 아닙니다. 정확히 무슨 일이 일어 났습니까? 예외가 있습니까? 코드 실행이 중지되면 어디에서 멈 춥니 까? – svick

+1

호출 코드는 어떻게 생겼는가? 당신의 메소드를 호출 할 때'Wait' 또는'Result'를 사용합니까? –

답변

3

다른 사람이 제안한 문제는 동기화 컨텍스트입니다. 기다리는 것은 기다리고있는 동기화 컨텍스트 (본질적으로 스레드)에서 실행을 다시 시작합니다. 해당 스레드가 이미 차단 된 경우 다른 것을 기다리면서 코드가 교착 상태가됩니다.

이렇게하려면 await에 대한 호출을 따라 ConfigureAwait(false)을 호출해야 런타임이 다른 스레드에서 계속됩니다.

다음 코드는 원활하게 실행됩니다. ConfigureAwait 호출을 제거하면 교착 상태가 _ 생합니다.

또한 xxxAsync 메서드를 사용하는 한 Task.Run에서 WCF 호출을 할 필요가 없습니다. 이렇게하면 코드가 훨씬 더 깨끗해집니다.

마지막으로 완료를 기다리고 싶다면 Task.WaAll()을 기다리는 대신 Task.WaitAll()을 사용해야합니다. 당신이 또 다른 ConfigureAwait() @Panagiotis Kanavos의 대답

protected void Page_Load(object sender, EventArgs e) 
    { 
     var results = GetThem().Result; 

    } 

    private async Task<Tuple<Cat,Dog,Pig>> GetThem() 
    { 
     Task<Cat> catAsync = GetCatAsync(); 
     Task<Dog> dogAsync = GetDogAsync(); 
     Task<Pig> pigAsync = GetPigAsync(); 

     await Task.WhenAll(catAsync, dogAsync, pigAsync).ConfigureAwait(false); 
     //better yet, 
     // Task.WaitAll(catAsync, dogAsync, pigAsync); 

     var cat = catAsync.Result; 
     var dog = dogAsync.Result; 
     var pig = pigAsync.Result; 
     return Tuple.Create(cat, dog, pig); 
    } 

    private async Task<Pig> GetPigAsync() 
    { 
     var cat = new Pig(); 
     var res = await GetGoogleSearchHTML("cat").ConfigureAwait(false); 
     using (StreamReader sr = new StreamReader(res.GetResponseStream())) 
     { 
      cat.Name = await sr.ReadToEndAsync().ConfigureAwait(false); 
     } 

     return cat; 
    } 

    public async Task<WebResponse> GetGoogleSearchHTML(string type) 
    { 
     System.Net.WebRequest request = System.Net.HttpWebRequest.Create(String.Format("http://www.google.com/search?noj=1&site=cat&source=hp&q={0}&oq=search", type)); 
     System.Net.WebResponse response = await request.GetResponseAsync().ConfigureAwait(false); 
     return response; 
    } 
+0

GetPigAsync 함수에서 async를 제거하고 Task.WaitAll을 사용하면 문제가 해결되었으며 현재 실행 중입니다. –

+0

흥미로운 점은 언제 어디서나 단위 테스트에서 발견되었지만 iis와 iis express에서는 후속 코드가 호출되지 않았다고합니다. ConfigureAwait (false)가 문제를 해결했습니다. 감사합니다. – JimSTAT

+0

어쨌든 원래의 컨텍스트를 차단하는 것을 찾아야합니다. 요청 스레드를 차단하면 비동기 실행의 이점이 없습니다. –

0

을 답을 읽은 후이 예제와 함께 작동 게시 . 코드 실행 시간 제한이 제거

+0

각 사용자는 5 ~ 10 초이므로 기다리는 사용자는 길지만 처리는 지연되지 않습니다. –

+0

Windows 이벤트 로그를 살펴보십시오. IIS가 요청을 중지하거나 풀을 재사용하기로 결정하면 거기에 메시지를 작성해야합니다. – alex

+0

작업을 생성 할 때 "장기 실행"힌트를 추가 할 수도 있습니다. –

0

시도의 web.config에 설정 될 수있는 기능에서 비동기를-기다리고 :

private Task<Cat> CatAsync() 
{ 
    return Task.Run(() => 
     { 
      //Use WCF to get some data from a service 
     }); 
} 

당신은 외부 함수에서 await를 유지할 수 있습니다. 설명이 옵션을 선택합니다 : - 내가 중 하나를 만들 자마자

Why does this async action hang?

+0

나는 그들을 대체하려고했지만 죽어가는 스레드와 같은 문제가 생겼어. –

-1

닷컴,

나는 (당신의 WCF 호출에 동기 WebRequest 클래스와 웹 응답을 사용하여), 코드 작업 있어요 WebResponse/Requests Async (WCF 호출을 수행하는 곳)에서 중단되었습니다.

private async Task<Cat> GetCatAsync() 
     { 
      Cat cat = new Cat(); ; 
      await Task.Run(() => 
      { 
       //Use WCF to get some data from a service 
       var res = GetGoogleSearchHTML("cat").Result; 
       using (StreamReader sr = new StreamReader(res.GetResponseStream())) 
       { 
        cat.catName = sr.ReadToEnd(); 
       } 
      }); 

      return cat; 
     } 

     public async Task<WebResponse> GetGoogleSearchHTML(string type) 
     { 
      System.Net.WebRequest request = System.Net.HttpWebRequest.Create(String.Format("http://www.google.com/search?noj=1&site=cat&source=hp&q={0}&oq=search",type)); 
      System.Net.WebResponse response = await request.GetResponseAsync(); 
      return response; 
     } 

     public class Dog { 
      public string dogName { get; set; } 
      } 


     public class Pig 
     { 
      public string pigName { get; set; } 
     } 


     public class Cat 
     { 
      public string catName { get; set; } 
     } 


     private async Task<Dog> GetDogAsync() 
     { 
      Dog dog = new Dog(); 

      await Task.Run(() => 
      { 
       WebResponse res = GetGoogleSearchHTML("dog").Result; 
       using (StreamReader sr = new StreamReader(res.GetResponseStream())) 
       { 
        dog.dogName = sr.ReadToEnd(); 
       } 
       //Use WCF to get some data from a service 
      }); 

      return dog; 
     } 

     private async Task<Pig> GetPigAsync() 
     { 
      Pig pig = new Pig(); ; 

      await Task.Run(() => 
      { 
       var res = GetGoogleSearchHTML("pig").Result; 
       using(StreamReader sr = new StreamReader(res.GetResponseStream())) 
       { 
        pig.pigName = sr.ReadToEnd(); 
       } 
       //Use WCF to get some data from a service 
      }); 

      return pig; 
     } 

     public async void GetTypes() 
     { 
     List<Task> taskList = new List<Task>() { }; 


      Task<Cat> catAsync = GetCatAsync(); 
      Task<Dog> dogAsync = GetDogAsync(); 
      Task<Pig> pigAsync = GetPigAsync(); 

     await Task.WhenAll(catAsync , dogAsync , pigAsync); 

     var cat= catAsync.Result; 
     var dog= dogAsync.Result; 
     var pig= pigAsync.Result; 
     } 



public WebApiResult GetResponses() 
{ 

GetTypes(); 

return new WebApiResult(); 

} 
+0

비동기 메서드 내에서 Task.Run을 호출하면 다른 비동기 메서드가 호출되지만 .Result 호출과 동 기적으로 실행됩니다. ...? –

+0

예,'await'과 동기식 대기를 결합하면 대개 교착 상태가 발생합니다. 그러나 이것이 영업 사원이 실제로하고있는 징후가 없으므로 이것이 대답이 아니라고 생각합니다. – svick

1

가 작동 얻었다을 추가 할 필요가 없습니다 Task.WaitAll()는 syncrhonization 컨텍스트하지 엉망 않습니다.여기에 내가 작업이

그 Google 직원 아웃 웹 API를 사용하여 IIS에서 작동하도록 방법을 정리 요약의 Web.config에

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> 

그런 다음

Task<Cat> cat= GetCat(); 
Task<Dog> dog= GetDog();  
Task.WaitAll(cat,dog,pig etc); 

NowUseTheValues(cat.Result,dog.Result); 
) WaitAll을 (작업을 생성하고 사용하는 추가의

작업은 비동기없이 일반 작업을해야한다 :

private Task<Cat> GetCat() 
{ 
    return Task.Run(() => { 
      return new Cat(); 
     }); 
} 
관련 문제