2013-06-08 3 views
2

나는 낸시/ASP.Net 프로젝트에서 일하고 있습니다. 다른 웹 서비스에서 데이터를 가져 오기 위해 WebRequest를 사용하려고 시도했으며 비동기 함수에서 요청을 구현했습니다. 함수에서 반환 된 작업을 기다리려고하면 무한정 차단된다는 문제가 있습니다. 간단한 코드는 다음과 같습니다.비동기 메소드에서 반환 된 작업 대기가 차단되는 이유는 무엇입니까?

using System.Net; 
using System.Threading.Tasks; 
using Nancy; 

public class TestModule : NancyModule{ 
    public TestModule() { 
     Get["/"] = p => "Hello, world"; 
     Get["/async/"] = p => { 
      var req = WebRequest.CreateHttp("http://localhost:13254/"); 

//   var responseTask = req.GetResponseAsync(); // this works! 
      var responseTask = getResponse(req); // this gets blocked! 
      var waitSuccess = responseTask.Wait(10000); 

      return waitSuccess ? "Yeah!" : "woooh!"; 
     }; 
    } 
    async Task<HttpWebResponse> getResponse(HttpWebRequest request) { 
     return (HttpWebResponse) await request.GetResponseAsync(); 
    } 
} 

코드는 NancyFx를 사용하지만 바닐라 ASP.Net 페이지에서도 마찬가지입니다. localhost : 13254의 서비스가 정상적으로 작동합니다. 요청의 GetResponseAsync()에서 직접 반환 된 작업을 사용하면 코드가 제대로 작동하지만 비동기 메서드로 래핑하면 차단됩니다.

코드에 어떤 문제가 있는지 알 수 있습니까? :(동기식 버전을 사용하도록 변경할 수 있지만 비동기 함수는 다른 자체 호스팅 서비스에서 작동합니다 ... 가능하면 여기에서도 동일한 코드를 사용하고 싶습니다.

답변

3

이 교착 상태 동작을 설명합니다 on my blogin a recent MSDN article.

는이 문제를 해결하려면, 당신도 사방 ConfigureAwait(false)를 사용하거나 동기 방법을 사용할 수 있습니다. 이상적인 솔루션은 Wait 또는 Result을 사용 결코 모든 방법을 await 사용하지하는 것입니다, 그러나 그것은 가능하지 않을 수 있습니다 귀하의 상황 (낸시가 async 대표자와 함께 작업 한 경우에만 작동합니다 (예 : Get["/async/"] = async p => { ... };).

+1

Nancy Async 베타 패키지를 사용하면 작동합니다. :) – Phill

+0

이것을 지적 해 주셔서 감사합니다 : D 나는 낸시 비동기를 아직 시도하지 않았으므로 잠시 동안 이걸 가지고 살아야합니다. – Ruxo

1

Stephen에서 제공 한 솔루션 외에도 Nancy Route 처리기의 루트에서 동기화 컨텍스트를 변경하는 것으로 해결됩니다. ..

using System; 
using System.Threading; 

namespace Utility.Async{ 
    static public class TPContext{ 
     static public T Call<T>(Func<T> handler) { 
      var currentContext = SynchronizationContext.Current; 
      SynchronizationContext.SetSynchronizationContext(null); 
      try { 
       return handler(); 
      }finally { 
       SynchronizationContext.SetSynchronizationContext(currentContext); 
      } 
     } 
    } 
} 

그냥이 기능

 Get["/async/"] = p => TPContext.Call(() => { 
      var req = WebRequest.CreateHttp("http://localhost:13254/"); 

      var responseTask = getResponse(req); 
      var waitSuccess = responseTask.Wait(10000); 

      return waitSuccess ? "Yeah!" : "woooh!"; 
     }); 

와 핸들러를 포장하고 그냥 내가 ASP.Net 컨텍스트를 필요가 있다고 생각하지 않습니다 ^^ 작동하고 실제로 나는 희망 :이 유틸리티 기능을 감안할 때 Nancy는 개념적으로 Asp.net과 다르게 작동하기 때문에 Nancy'd는 자체 동기화 환경을 만듭니다.