我正在尝试学习如何实现异步模式以同时查询多个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()作为回调函数吗?或者这会产生大量的线程并且实际上减慢了速度。
谢谢。
答案 0 :(得分:1)
查看静态WaitHandle.WaitAll(WaitHandle[] waitHandles)方法。该页面上有一个很棒的代码示例。
通常,任何实现异步模式的类都将定义表单的方法:
IAsyncResult BeginXXX(AsyncCallback callback, Object state);
Result EndXXX(IAsyncResult asyncResult);
调用BeginXXX
以异步方式调用该方法,并调用EndXXX
强制当前线程等待,直到异步方法完成。
要进行多次异步调用,您需要做的就是根据需要多次调用BeginXXX
,然后调用WaitHandle.WaitAll(...)
传入IAsyncResult.AsyncWaitHandle以获取您想要的所有调用等待。
要回答第二个问题,是的,您可以递归使用GetAsynComplete
。 state
调用的BeginXXX
参数用于标识请求,可以通过IAsyncResult.UserState
属性访问 - 因此您可以将请求与响应进行匹配。
这是否是一件好事更具主观性。通常,异步调用通过线程池进行,因此一次创建大量的线程可能会耗尽可用的线程,之后,新的调用将排队,直到线程可用。在线程之间切换有一些开销,但与同步执行它所花费的时间相比,这可能不会很大(除非你有非常多的线程)。