当我尝试对特定任务进行并行处理时,需要花费大量时间才能完成。也就是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>
时,如下面的代码那样,我收到服务器错误,因为该过程无法继续&#39;异步&#39;。任何帮助将受到高度赞赏。
更新 - 我确实更改了下面的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:
答案 0 :(得分:2)
查看异常:
异步操作方法'_Index'返回一个无法同步执行的Task。
听起来有些东西无法处理异步代码。正常的MVC操作适用于async
,所以它必须是其他的东西。像这样:
V:中的Vibrant.Controllers.BaseController.ExecuteCore():Vibrant3_SVN_Latest \ Vibrant \ Vibrant \ Controllers \ BaseController.cs:第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
与第一个示例相同。