异步WCF查询最后一步

时间:2011-03-26 00:37:26

标签: c# wcf asynchronous asynchronous-wcf-call

我正在尝试学习如何实现异步模式以同时查询多个wcf服务,但不知道如何检查所有并发调用是否完整。我有一个执行异步操作的类,然后在操作完成时添加到List:

   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);
                }
            }
        }    
    }

我的两个问题是:

1)如何确保在所有并发呼叫完成后我只获取列表结果?例如,如果在循环中调用GetAsync(),启动多个并发进程,我需要确保在将数据从List Result中取出之前它们都已完成。

2)我可以在GetContinuation()调用中使用BeginExecute()并递归使用相同的方法GetAsyncComplete()作为回调函数吗?或者这会产生大量的线程并且实际上减慢了速度。

谢谢。

1 个答案:

答案 0 :(得分:1)

查看静态WaitHandle.WaitAll(WaitHandle[] waitHandles)方法。该页面上有一个很棒的代码示例。

通常,任何实现异步模式的类都将定义表单的方法:

IAsyncResult BeginXXX(AsyncCallback callback, Object state);

Result EndXXX(IAsyncResult asyncResult);

调用BeginXXX以异步方式调用该方法,并调用EndXXX强制当前线程等待,直到异步方法完成。

要进行多次异步调用,您需要做的就是根据需要多次调用BeginXXX,然后调用WaitHandle.WaitAll(...)传入IAsyncResult.AsyncWaitHandle以获取您想要的所有调用等待。

要回答第二个问题,是的,您可以递归使用GetAsynCompletestate调用的BeginXXX参数用于标识请求,可以通过IAsyncResult.UserState属性访问 - 因此您可以将请求与响应进行匹配。

这是否是一件好事更具主观性。通常,异步调用通过线程池进行,因此一次创建大量的线程可能会耗尽可用的线程,之后,新的调用将排队,直到线程可用。在线程之间切换有一些开销,但与同步执行它所花费的时间相比,这可能不会很大(除非你有非常多的线程)。