c#线程异步问题
发布时间:2020-12-15 07:56:12 所属栏目:百科 来源:网络整理
导读:我有一些代码,当被调用时调用webservice,查询数据库并从本地缓存中获取值.然后它将这三个动作的返回值组合起来以产生结果.我没有按顺序执行这些操作,而是想并行异步执行它们.这是一些虚拟/示例代码: var waitHandles = new ListWaitHandle();var wsResult =
我有一些代码,当被调用时调用webservice,查询数据库并从本地缓存中获取值.然后它将这三个动作的返回值组合起来以产生结果.我没有按顺序执行这些操作,而是想并行异步执行它们.这是一些虚拟/示例代码:
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之前继续执行.这周围有一个整洁/优雅的方式吗? 注意:我应该补充说这会影响dbResult,因为queryDB是要发信号的最后一个等待句柄. 更新:虽然我接受了菲利普的答案,但是在安德烈的评论之后,我应该补充说这也有效: 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,cacheResult)); 解决方法
不幸的是,在EndInvoke()调用返回之前,始终会发出WaitHandle信号.这意味着你不能依赖于此.
如果你不能使用4.0,那么线程或手动等待处理系统可能会有序(或者可怕的Sleep()hack!).您还可以使用Invoked方法设置结果(因此在设置结果值后会发生EndInvoke),但这意味着将结果移动到共享位置,而不是局部变量 – 可能需要进行小的重新设计. 或者,如果你可以使用4.0,我会 – System.Threading.Tasks充满了’很棒的东西.你可以重写为: var tasks = new List<Task>(); var wsResult = 0; string dbResult = null; var cacheResult = ""; tasks.Add( new Task( ()=> wsResult = CallWebService())); tasks.Add( new Task( ()=> dbResult = QueryDB())); tasks.Add( new Task( ()=> cacheResult = QueryLocalCache())); tasks.ForEach( t=> t.Start()); Task.WaitAll( tasks.ToArray()); Console.WriteLine(string.Format(dbResult,cacheResult)); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |