2016-03-01 140 views
0

正如我試圖在需要花費大量時間才能完成的特定任務上進行並行處理一樣。那就是,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>像下面的代碼,然後我收到服務器錯誤的過程中不能進行「異步」。任何幫助將不勝感激。

更新 - 我沒有改變的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

請參閱下面的答案,注意在代碼中缺少一個'await'和'ToListAsync'。 – Igor

+0

所以''等待ReturnAmount''更改錯誤信息或同樣的錯誤? –

+0

我的更新編譯得很好。但引發運行時異常。 – DonMax

回答

2

望着例外:

異步操作方法「 _Index'返回一個任務,其中不能同步執行。

這聽起來像是某些東西無法處理異步代碼。正常的MVC操作與async正常工作,所以它必須是別的東西。就像這樣:

Vibrant.Controllers.BaseController.ExecuteCore()在E:\ Vibrant3_SVN_Latest \充滿活力\充滿活力\ \控制器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保持與您的第一個例子。

+0

Sorries,我無法理解你的解釋。所以,如果你可以發佈整個修改後的代碼,那麼將高度讚賞。 – DonMax

+0

@DonMax:抱歉,那不是我滾動的方式。我的答案的哪一部分不清楚? –

+0

我不明白。你希望我改變我的代碼,以同步的方式,即不使用任務,異步和等待任何地方? – DonMax