2011-03-26 2 views
0

여러 wcf 서비스를 동시에 쿼리하기 위해 비동기 패턴을 구현하는 방법을 배우려하지만 모든 동시 호출이 완료되었는지 확인하는 방법을 알지 못합니다. 비동기 WCF 쿼리 최종 단계

public static class ODataAsync 
    { 
     static DataServiceContext ServiceContext; 
     static List<DynamicEntity> Results = new List<DynamicEntity>(); 

     private static void GetAsync(string serviceUri, NameValueCollection queryOptions, IAuthenticationScheme authenticationScheme) 
     { 
      string baseUri; 
      string entitySet; 
      string entityKey; 
      string queryString; 
      ValidateServiceUri(serviceUri, out baseUri, out entitySet, out entityKey, out queryString); 
      string resource = !string.IsNullOrEmpty(entityKey) ? entitySet + "(" + entityKey + ")" : entitySet; 

      DataServiceContext context = new DataServiceContext(new Uri(baseUri)); 
      context.IgnoreMissingProperties = true; 

      ServiceContext = context; 

      DataServiceContextHandler handler = new DataServiceContextHandler(authenticationScheme); 
      handler.HandleGet(context); 

      DataServiceQuery<EntryProxyObject> query = context.CreateQuery<EntryProxyObject>(resource); 

      NameValueCollection options = HttpUtility.ParseQueryString(queryString); 
      options.Add(queryOptions); 

      foreach (string key in options.AllKeys) 
      { 
       query = query.AddQueryOption(key, options[key]); 
      } 

      try 
      { 
       query.BeginExecute(GetAsyncComplete, query); 
      } 
      catch (DataServiceQueryException ex) 
      { 
       throw new ApplicationException("An error occurred during query execution.", ex); 
      } 
     } 

     private static void GetAsyncComplete(IAsyncResult result) 
     { 
      QueryOperationResponse<EntryProxyObject> response = 
       ((DataServiceQuery<EntryProxyObject>)result).EndExecute(result) as QueryOperationResponse<EntryProxyObject>; 

      IList<dynamic> list = new List<dynamic>(); 

      foreach (EntryProxyObject proxy in response) 
      { 
       DynamicEntity entity = new DynamicEntity(proxy.Properties); 
       Results.Add(entity); 
      } 

      while (response.GetContinuation() != null) 
      { 
       Uri uri = response.GetContinuation().NextLinkUri; 

       response = ServiceContext.Execute<EntryProxyObject>(uri) as QueryOperationResponse<EntryProxyObject>; 

       foreach (EntryProxyObject proxy in response) 
       { 
        DynamicEntity entity = new DynamicEntity(proxy.Properties); 
        Results.Add(entity); 
       } 
      } 
     }  
    } 

내 2 개 질문

은 다음과 같습니다 : 나는 다음 비동기 작업을 실행하고 클래스가 완료 작업으로 목록에 추가 한

1) 나는 단지 (목록의 결과를 얻을 수 있도록 어떻게들) 모든 동시 호출이 완료되면? 예를 들어 루프 내에서 GetAsync()를 호출하는 경우 여러 동시 프로세스를 시작하면 목록 결과에서 데이터를 가져 오기 전에 모두 완료되었는지 확인해야합니다.

2) GetContinuation() 호출에서 BeginExecute()를 사용할 수 있으며 콜백 함수와 동일한 GetAsyncComplete() 메서드를 재귀 적으로 사용할 수 있습니까? 아니면 스레드를 생성하고 실제로 느려지는 것들을 만듭니다.

감사합니다.

답변

1

정적 인 WaitHandle.WaitAll(WaitHandle[] waitHandles) 방법을 살펴보십시오. 이 페이지에는 훌륭한 코드 예제가 있습니다.

일반적으로, 비동기 패턴을 구현하는 모든 클래스는 양식 방법을 정의합니다 :

BeginXXX를 호출
IAsyncResult BeginXXX(AsyncCallback callback, Object state); 

Result EndXXX(IAsyncResult asyncResult); 

비동기 메소드를 호출하고, EndXXX를 호출하면 비동기 메소드가 완료 될 때까지 현재의 thread를 강제로.

여러 비동기 호출을 만들려면, 당신이해야 할 모든 필요한 BeginXXX 여러 번 호출 한 다음 대기하려는 통화 모두에 대해 IAsyncResult.AsyncWaitHandle 전달 WaitHandle.WaitAll(...)를 호출합니다.

두 번째 질문에 대답하려면 예, GetAsynComplete을 재귀 적으로 사용할 수 있습니다. BeginXXX 호출에 제공된 state 매개 변수는 요청을 식별하는 데 사용되며 IAsyncResult.UserState 속성을 통해 액세스 할 수 있으므로 요청을 응답과 일치시킬 수 있습니다.

이것이 좋은지 아닌지는 좀 더 주관적입니다. 대개 비동기 호출은 스레드 풀을 통해 이동하므로 한 번에 많은 수의 스레드를 생성하면 사용 가능한 스레드를 모두 소모 할 수 있습니다. 그런 다음 새 스레드는 스레드를 사용할 수있게 될 때까지 대기열에 저장됩니다. 스레드 간 전환에 약간의 오버 헤드가 있지만, 동기식으로 수행하는 데 걸린 시간과 비교할 때 (스레드 수가 매우 큰 경우가 아니면) 중요하지 않을 수 있습니다.