我有一些代码,当调用时会调用一个Web服务,查询数据库并从本地缓存中获取值。然后它将这三个操作的返回值组合起来生成结果。我想要的是并行异步执行这些操作,而不是按顺序执行。以下是一些虚拟/示例代码:
var waitHandles = new List<WaitHandle>();
var wsResult = 0;
Func<int> callWebService = CallWebService;
var wsAsyncResult = callWebService.BeginInvoke(res => { wsResult = callWebService.EndInvoke(res); }, null);
waitHandles.Add(wsAsyncResult.AsyncWaitHandle);
string dbResult = null;
Func<string> queryDB = QueryDB;
var dbAsyncResult = queryDB.BeginInvoke(res => { dbResult = queryDB.EndInvoke(res); }, null);
waitHandles.Add(dbAsyncResult.AsyncWaitHandle);
var cacheResult = "";
Func<string> queryLocalCache = QueryLocalCache;
var cacheAsyncResult = queryLocalCache.BeginInvoke(res => { cacheResult = queryLocalCache.EndInvoke(res); }, null);
waitHandles.Add(cacheAsyncResult.AsyncWaitHandle);
WaitHandle.WaitAll(waitHandles.ToArray());
Console.WriteLine(string.Format(dbResult, wsResult, cacheResult));
问题在于最后一行会抛出一个错误,因为在执行时dbResult仍然为null。一旦调用queryDB.EndInvoke,WaitHandle被标记,执行继续,而queryDB.EndInvoke的结果被分配给dbResult之前。有没有巧妙/优雅的方法解决这个问题?注意:我应该补充说明,这是因为queryDB是最后一个被标记的等待句柄,所以会影响到dbResult。更新:虽然我接受了Philip的答案,但根据Andrey的评论,我应该补充说明这也可以工作:
var waitHandles = new List<WaitHandle>();
var wsResult = 0;
Func<int> callWebService = CallWebService;
var wsAsyncResult = callWebService.BeginInvoke(null, null);
waitHandles.Add(wsAsyncResult.AsyncWaitHandle);
string dbResult = null;
Func<string> queryDB = QueryDB;
var dbAsyncResult = queryDB.BeginInvoke(null, null);
waitHandles.Add(dbAsyncResult.AsyncWaitHandle);
var cacheResult = "";
Func<string> queryLocalCache = QueryLocalCache;
var cacheAsyncResult = queryLocalCache.BeginInvoke(null, null);
waitHandles.Add(cacheAsyncResult.AsyncWaitHandle);
WaitHandle.WaitAll(waitHandles.ToArray());
var wsResult = callWebService.EndInvoke(wsAsyncResult);
var dbResult = queryDB.EndInvoke(dbAsyncResult);
var cacheResult = queryLocalCache.EndInvoke(cacheAsyncResult);
Console.WriteLine(string.Format(dbResult, wsResult, cacheResult));