2016-03-01 3 views
0

Поскольку я пытался выполнить параллельную обработку по конкретной задаче, где требуется огромное время для завершения. То есть, ForEach in Linq. Пожалуйста, обратите внимание на код, приведенный ниже,Выполнение определенной задачи параллельно с использованием Await и Async

код

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> как код ниже, то я получаю ошибку сервера как процесс не может продолжаться «Асинхронный». Любая помощь будет высоко оценена.

Update - Я изменил метод 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

, так что '' wait ReturnAmount'' меняет сообщение об ошибке или такую ​​же ошибку? –

+0

Мое обновление отлично составило. но выдает исключение во время выполнения. – DonMax

ответ

2

Глядя на исключение:

Метод асинхронного действия " _Index 'возвращает задачу, которая не может выполняться синхронно.

Звучит так, как будто не может обрабатывать асинхронный код. Нормальные действия MVC отлично работают с async, поэтому это должно быть что-то еще. Как это:

Vibrant.Controllers.BaseController.ExecuteCore() в е: \ Vibrant3_SVN_Latest \ Vibrant \ Vibrant \ Контроллеры \ 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

Сорри, я не могу понять ваше объяснение. поэтому, если бы вы могли опубликовать весь модифицированный код, тогда он будет высоко оценен. – DonMax

+0

@DonMax: Извините, это не так, как я рулон. Какая часть моего ответа не ясна? –

+0

Не понимаю. Вы хотите, чтобы я менял весь свой код на синхронный путь, т. Е. Без использования 'Task, async и await'anywhere ?? – DonMax