2015-01-30 2 views
1

У меня есть приложение MVC 4.0, ориентированное на targetFramework = "4.5".Async не работает в асинхронном контроллере mvc 4.0

Я должен в основном преобразовать существующую функциональность обработки файлов с синхронной асинхронной (так что для большого пользователя файла не нужно ждать другой задачи).

Мой код

[HttpPost] 
     public async Task<ActionResult> FileUpload(HttpPostedFileBase fileUpload)  
{ 

Coreservice objVDS = new Coreservice(); 

    //validate the contents of the file 
model =objVDS. ValidateFileContents(fileUpload); 

// if file is valid start processing asynchronously 
    await Task.Factory.StartNew(() => { objVDS.ProcessValidFile(model); },        CancellationToken.None, 
        TaskCreationOptions.DenyChildAttach, 
        TaskScheduler.FromCurrentSynchronizationContext()); 

return view(); 


} 

В основном я хочу, чтобы вызвать асинхронный метод, который в сфере услуг, который делает операции с базами данных (diffrent проект).

Я хочу, чтобы асинхронный процесс имел доступ к контексту в методах служб. Вот почему я использую TaskScheduler.FromCurrentSynchronizationContext() в Task.Factory.StartNew().

метод Услуга, как следующий, в котором, в зависимости от типа файла, второй сервис вызывался для операций с данными

public async task ProcessValidFile(fileProcessDataModel model) 
{ 
employeeWorkedDataservice service =new employeeWorkedDataservice() 

await Task.Factory.StartNew(() => 
             { 
              service .ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source); 
             }, 
             CancellationToken.None, 
             TaskCreationOptions.DenyChildAttach, 
           TaskScheduler.FromCurrentSynchronizationContext());  

} 

ProcessEmployeeDataFile возвращает недействительным и его не асинхронной метод. При выполнении вышеуказанного кода он не возвращается к контроллеру до завершения обработки данных. Я думаю, что здесь что-то не хватает. Пожалуйста, направляйте меня к решению.

Спасибо, Amol

+0

Предполагаете, что вы уже прочитали https://msdn.microsoft.com/en-us/library/hh191443.aspx? – Nzall

+0

Да; я что-то упускаю? – amol

ответ

3

Похоже, вы поняли хау await работы.

Читать эту https://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_WhatHappensUnderstandinganAsyncMethod

Настройка что-то работает в задачи позволит ему работать в асинхронном режиме, так что вы можете сделать что-то другое, пока он работает.

Если вам нужно, чтобы результат был продолжен, вы используете ключевое слово await.

Создавая свою задачу немедленно, вы мгновенно блокируете до тех пор, пока задача не будет решена; что делает его эффективно синхронным.

Если вы с удовольствием вернетесь к своему представлению, не дожидаясь завершения обработки, я не думаю, что вам нужно await, так как вы ни в коем случае не хотите ждать результата операции.

public task ProcessValidFile(fileProcessDataModel model) 
{ 
    employeeWorkedDataservice service =new employeeWorkedDataservice() 

    return Task.Factory.StartNew(() => 
    { 
     service.ProcessEmployeeDataFile(model.DataSetToProcess, OriginalFileName, this, model.Source); 
    }, 
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.FromCurrentSynchronizationContext());  
} 

[HttpPost] 
public ActionResult FileUpload(HttpPostedFileBase fileUpload)  
{ 

    Coreservice objVDS = new Coreservice(); 

    //validate the contents of the file 
    model =objVDS. ValidateFileContents(fileUpload); 

    // if file is valid start processing asynchronously 
    // This returns a task, but if we're not interested in waiting 
    // for its results, we can ignore it. 
    objVDS.ProcessValidFile(model); 

    return view(); 
} 

Что касается ваших комментариев:

Я бы серьезно рассмотреть не проходящий контроллер к вашим услугам, или имеющему свой сервис опирающегося на сессии и контексте, так как вы плотно соединений бизнеса-логику к вашему API-контроллер.

Получите необходимые вам биты с контроллера, пока вы находитесь в нем, и передайте их на службу.

+0

спасибо за ваш ответ, но даже после возвращения view(); пользователь не получает представление до завершения загрузки файла на фоне. Имеет ли это связано с возвращением Task.Factory.StartNew (() => { service.ProcessEmployeeDataFile (model.DataSetToProcess, OriginalFileName, это, model.Source); }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.FromCurrentSynchronizationContext()); ? – amol

+0

во время отладки, я вижу, что вы видите обратный возврат(); но пользователь по-прежнему заблокирован – amol

+0

ok, поэтому я закомментировал CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.FromCurrentSynchronizationContext(); теперь он показывает страницу пользователю; но теперь у меня нет доступа к значениям контекста и сеанса в новой задаче, поэтому он прерывает приложение. как сохранить контекст и сеанс в этом случае? – amol

3

Я должен в основном преобразовать существующую функциональность обработки файлов с синхронной асинхронной (так что для большого пользователя файла не нужно ждать другой задачи).

Это не то, что async делает; как я описываю в своем блоге, async does not change the HTTP protocol.

Что вы хотите, это некоторая форма «огня и забыть» на ASP.NET. У меня есть еще одна запись в блоге, что covers a few solutions. Обратите внимание, что использование Task.Factory.StartNew является самым опасным из всех этих решений.

Лучшее (прочитанное: наиболее надежное) решение заключается в использовании надлежащей распределенной архитектуры: ваше приложение ASP.NET должно создать описание выполняемой работы и поместить ее в надежную очередь (например, MSMQ); затем иметь независимый бэкэнд (например, службу Win32), который обрабатывает очередь. Это сложный, но гораздо менее подверженный ошибкам, чем попытка заставить ASP.NET делать то, что он никогда не хотел делать.

+0

Поскольку я не могу использовать контекст в Task.Factory.StartNew ((), я изменил его на Task.Run(); – amol

+0

@amol: 'Task.Run' также опасен в ASP.NET и не рекомендуется. –

+0

@ Stephen Cleary Thank You !!! Я проигнорировал ваши комментарии, так как мне пришлось заполнить его для демонстрации (он работал для небольшого количества записей) .. и позже получил проблему рециркуляции нитей для больших файлов. Теперь переходите к вашему блогу. еще раз. – amol

Смежные вопросы