使用 Await 和 Async 并行运行特定任务
本文关键字:任务 运行 并行 Await Async 使用 | 更新日期: 2023-09-27 18:36:49
因为我试图对需要大量时间才能完成的特定任务进行并行处理。也就是说,ForEach in Linq
.请考虑以下代码,
法典
public async Task<List<int>> ReturnRoutAsync(int UserId, int Id)
{
return await Task.FromResult(db.RoutingListMembers.Where(a => a.RoutingListId == UserId && a.User.UserDeptId == Id).Select(a => a.UserId.Value).ToList());
}
public async Task<List<int?>> CareAllocCount(List<UserWithDeptId> RouteList)
{
return await Task.FromResult(RouteList.Where(f => f.PoReceiptId == f.PoReceiptId).Select(f => f.UserId).ToList());
}
public async Task<int> UsersCount(int? UserId)
{
return await Task.FromResult(db.RoutingListMembers.Where(x => x.RoutingListId == UserId).Select(x => x.UserId).Count());
}
public async Task<List<UserWithDeptId>> GetRoutingList(List<UserWithDeptId> RouteList, int Id)
{
await RouteList.ForEachAsync(async d => { d.RouteUserIdList = await ReturnRoutAsync(d.UserId.Value, Id); d.CareAllocationCnt = await CareAllocCount(RouteList); d.TotRouteUsers = await UsersCount(d.UserId); });
return RouteList;
}
public async Task<decimal> ReturnAmount(int Id, int Year)
{
.... (Some other Logic) ....
var RouteList = Model.Where(asd => asd.Year == Year).ToList();
RouteList = await GetRoutingList(RouteList, Id);
.... (Other logic here)....
var Amount = NewModelList.Sum(asd => asd.Allocated_Cost_to_Dept); // returns decimal
return Amount;
}
[GridAction]
public ActionResult _Index(int Year, int? page)
{
var model = (from Dept in db.UserDepts
select new ReviewHead
{
Header = Dept.Description,
DeptId = Dept.Id,
}).ToList();
List<ReviewHead> NewList = new List<ReviewHead>();
foreach (var temp in model)
{
ReviewHead RH = new ReviewHead();
RH.Amount = ReturnAmount(temp.DeptId, Year); // I am getting the compiler error saying that it cannot convert Task<decimal> to decimal.
RH.DeptId = temp.DeptId;
RH.Header = temp.Header;
NewList.Add(RH);
}
return View(new GridModel(NewList));
}
public static async Task ForEachAsync<T>(this List<T> list, Func<T, Task> func)
{
foreach (var value in list)
{
await func(value);
}
}
当我将上面的一个更改为使用类似以下代码Task<ActionResult>
时,我收到服务器错误,因为该过程无法"异步"进行。任何帮助将不胜感激。
更新 - 我确实更改了操作结果方法,如下所示
[GridAction]
public async Task<ActionResult> _Index(int Year, int? page)
{
var model = (from Dept in db.UserDepts
select new ReviewHead
{
Header = Dept.Description,
DeptId = Dept.Id,
}).ToList();
List<ReviewHead> NewList = new List<ReviewHead>();
foreach (var temp in model)
{
ReviewHead RH = new ReviewHead();
RH.Amount = await ReturnAmount(temp.DeptId, Year);
RH.DeptId = temp.DeptId;
RH.Header = temp.Header;
NewList.Add(RH);
}
return View(new GridModel(NewList));
}
运行时错误
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=The asynchronous action method '_Index' returns a Task, which cannot be executed synchronously.
Source=System.Web.Mvc
StackTrace:
at System.Web.Mvc.Async.TaskAsyncActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at Vibrant.Controllers.BaseController.ExecuteCore() in e:'Vibrant3_SVN_Latest'Vibrant'Vibrant'Controllers'BaseController.cs:line 42
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.Controller.<>c__DisplayClass19.<BeginExecute>b__13()
at System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
at System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag)
at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncResultWrapper.End[TResult](IAsyncResult asyncResult, Object tag)
at System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
InnerException:
查看异常:
异步操作方法"_Index"返回一个无法同步执行的任务。
听起来有些东西无法处理异步代码。正常的MVC操作可以正常工作async
,所以它一定是别的东西。喜欢这个:
Vibrant.Controllers.BaseController.ExecuteCore() in e:''Vibrant3_SVN_Latest''Vibrant''Vibrant''Controllers''BaseControllers.cs:line 42
听起来像"充满活力的" - 不管是什么 - 需要更新以启用异步请求。
同时,您必须使代码同步。这并不太难,因为代码实际上已经同步了。
特别是,此方法:
public async Task<List<int>> ReturnRoutAsync(int UserId, int Id)
{
return await Task.FromResult(db.RoutingListMembers.Where(a => a.RoutingListId == UserId && a.User.UserDeptId == Id).Select(a => a.UserId.Value).ToList());
}
有一个不必要的async
/await
,它只是解开一个任务,然后将结果包装回一个任务中,所以可以删除这些:
public Task<List<int>> ReturnRoutAsync(int UserId, int Id)
{
return Task.FromResult(db.RoutingListMembers.Where(a => a.RoutingListId == UserId && a.User.UserDeptId == Id).Select(a => a.UserId.Value).ToList());
}
此外,Task.FromResult
是同步操作。这个方法根本没有异步,所以我们可以让它同步。由于无论如何它都是同步的,因此同步表示更自然:
public List<int> ReturnRout(int UserId, int Id)
{
return db.RoutingListMembers.Where(a => a.RoutingListId == UserId && a.User.UserDeptId == Id).Select(a => a.UserId.Value).ToList();
}
对方法执行此操作后,您的逻辑只是:
public decimal ReturnAmount(int Id, int Year)
{
.... (Some other Logic) ....
var RouteList = Model.Where(asd => asd.Year == Year).ToList();
RouteList = GetRoutingList(RouteList, Id);
.... (Other logic here)....
var Amount = NewModelList.Sum(asd => asd.Allocated_Cost_to_Dept); // returns decimal
return Amount;
}
_Index
与您的第一个示例相同。