0

複数の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()を再帰的に使用できますか?または、それは大量のスレッドを作成し、実際に物事を遅くしますか?

ありがとうございました。

4

1 に答える 1

1

静的なWaitHandle.WaitAll(WaitHandle [] waitHandles)メソッドを見てください。そのページには素晴らしいコード例があります。

通常、非同期パターンを実装するクラスは、次の形式のメソッドを定義します。

IAsyncResult BeginXXX(AsyncCallback callback, Object state);

Result EndXXX(IAsyncResult asyncResult);

呼び出すBeginXXXとメソッドが非同期に呼び出され、呼び出すとEndXXX現在のスレッドが非同期メソッドが完了するまで待機します。

複数の非同期呼び出しを行うにはBeginXXX、必要な回数だけWaitHandle.WaitAll(...)呼び出してから、待機するすべての呼び出しに対してIAsyncResult.AsyncWaitHandleを渡して呼び出すだけです。

GetAsynComplete2番目の質問に答えるために、はい、再帰的に使用できます。callに指定されたstateパラメーターは、リクエストを識別するために使用され、プロパティBeginXXXを介してアクセスできるため、リクエストをレスポンスに一致させることができます。IAsyncResult.UserState

これが良いことであるかどうかは、もう少し主観的です。通常、非同期呼び出しはスレッドプールを経由するため、一度に多数の呼び出しを作成すると、使用可能なスレッドが使い果たされる可能性があり、その後、スレッドが使用可能になるまで新しい呼び出しがキューに入れられます。スレッド間の切り替えにはいくらかのオーバーヘッドがありますが、同期的に行うのにかかる時間と比較すると、(スレッドの数が非常に多い場合を除いて)おそらくそれほど重要ではありません。

于 2011-03-26T15:15:14.417 に答える