Есть несколько вопросов, которые касаются работы асинхронного контроллера, но никто не имеет отношения к тому, что мне нужно. надеюсь, кто-то уже это сделал и может сказать мне, что я делаю что-то неправильно.AsyncController, используемый для запуска консольного приложения
У меня есть комбинация веб-приложения, которое занимается настройкой задач и консольной консольной программой, которая занимается запуском настроенных задач. Я хотел иметь возможность запускать задачи из веб-приложения, нажав кнопку, на которой элемент управления немедленно возвращается пользователю, а задача выполняется в фоновом режиме. AsyncController кажется идеальным сочетанием. Оба приложения обращаются к одной базе данных с использованием EF6, инъекции зависимостей Unity и SQL Server 2012. Веб-интерфейс предназначен для .NET 4.5 на MVC4.
Я могу запустить консольное приложение отлично, без заминки. Я также могу запустить запуск из веб-интерфейса с помощью кода ниже. Единственная проблема заключается в том, что при запуске через веб-приложение задача будет выполняться до точки (я могу видеть ее в журналах (Nlog)), но она прекращает выполнение до тех пор, пока я не перестрою решение. Решение содержит оба приложения, которые также заменят. exe запускается. Когда я запускаю консольное приложение, я не получаю никаких пауз.
Это мой первый опыт использования Task, и я тоже немного застенчив с классом Process. Пожалуйста, не будьте слишком суровыми, если я делаю что-то невероятно глупое.
Вот код для контроллера:
public class TaskRunnerController : AsyncController
{
private readonly ITaskProcessService _taskProcessService;
private readonly IAuthenticationContext _context;
private readonly IServiceBase<Task> _taskService;
public TaskRunnerController(ITaskProcessService taskProcessService,
IAuthenticationContext context,
IServiceBase<Task> taskService)
{
_taskProcessService = taskProcessService;
_context = context;
_taskService = taskService;
}
private string TaskRunnerExe
{
get
{
var setting = ConfigurationManager.AppSettings["TaskRunner.Exe"];
Guard.Against<ConfigurationErrorsException>(string.IsNullOrEmpty(setting), "Missing configuration setting: TaskRunner.Exe");
return setting;
}
}
[CustomAuthorize(typeof(CanRun))]
public ActionResult RunTaskAsync(long id)
{
var task = _taskService.Find(i => i.TaskId == id);
Guard.AgainstLoad(task, id);
var fileInfo = new FileInfo(TaskRunnerExe);
Guard.Against<ConfigurationErrorsException>(!fileInfo.Exists, "TaskRunner could not be found at specified location: {0}", TaskRunnerExe);
var taskProcess = _taskProcessService.Schedule(task, _context.Principal.Identifier);
AsyncManager.OutstandingOperations.Increment();
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
ProcessStartInfo info = new ProcessStartInfo(fileInfo.FullName,
string.Format("{0} {1}", task.TaskId, taskProcess.TaskProcessId));
info.UseShellExecute = false;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.CreateNoWindow = true;
var process = new Process { StartInfo = info, EnableRaisingEvents = true };
process.Exited += (sender, e) =>
{
AsyncManager.OutstandingOperations.Decrement();
};
process.Start();
});
if (_context.Principal.HasPermission<CanViewList>())
return RedirectToAction("Index", "Tasks");
return RedirectToAction("Index", "Home");
}
public ActionResult RunTaskProgress()
{
return View();
}
public ActionResult RunTaskCompleted()
{
return Content("completed", "text/plain");
}
}
Зависимости:
- taskProcessService: хранилище для каждого события задачи выполняется
- контекста: хранит информацию о текущем пользователе
- taskService : репозиторий для задач
Консольное приложение (.exe) выходит, когда оно полностью завершено. Как я уже упоминал, при вызове через веб-приложение задача заканчивается только после того, как я перестрою приложение - на данный момент он делает все, что нужно - кажется, что он работал все время, он просто прекратил ведение журнала или отчет в какой-то момент в процессе.
Возможно, это важно. У меня была другая попытка без контроллера Async, но с той же настройкой - запустить Process, завернутый в задачу, которая имела тот же конечный эффект. Я думал, что процесс был убит, когда основной поток был возвращен в пул, поэтому я попробовал AsyncController.
Если я открываю диспетчер задач, я вижу, что процесс exe сидит там без дела. Приложение регистрирует прогресс до точки, но затем просто сидит там. Это проблема с VS? Я использую VS2012.
Неправильно ли я превратить процесс в задачу? Есть ли способ запустить исполняемый файл непосредственно через класс Task и класс Action?
Большое спасибо за понимание.
Только после мысли: у меня создалось впечатление, что AsyncController должен служить именно этой цели - ударом долгого процесса и возвращает поток запросов обратно в пул. Когда процесс завершен, из пула берется другой поток для обработки ответа. Разве это не то, что происходит? –
Вид. Вы все еще должны ждать завершения процесса. Вы не можете завершить запрос, иначе дерево задач будет очищено. Поток возвращается в пул, но вы все еще ожидаете завершения задачи. –