2013-02-15 92 views
7

我有一个MVC4 API REST试图在新线程中启动一个进程。我正在使用框架4.5并尝试使用同步并等待clausules。MVC4 WebApi进程启动器

我的代码如下所示:

[AcceptVerbs("POST")] 
public HttpResponseMessage Launch(string id) 
{ 
    runProcessAsync(id); // 1               

    return Request.CreateResponse(HttpStatusCode.Accepted); // 2 
} 

protected async void runProcessAsync(string id) 
{ 
    int exitcode = await runProcess(id); // 3 
    string exitcodesz = string.Format("exitcode: {0}", exitcode); // 4 
    // do more stuff with exitcode 
} 

protected Task<int> runProcess(string id) 
{ 
    var tcs = new TaskCompletionSource<int>(); 

    var process = new Process 
    { 
     StartInfo = { FileName = @"C:\a_very_slow_task.bat" }, 
      EnableRaisingEvents = true 
     }; 
     process.Exited += (sender, args) => tcs.SetResult(((Process)sender).ExitCode);    

     process.Start(); 

     return tcs.Task; 
    } 
} 

理想的情况下,有人将执行API REST调用(/任务/ slowtask /发射)与POST动词和期望202(接受)非常快。

使用Fiddler Web调试器我发出请求,代码进入Launch(// 1),然后进入await(// 3),慢速任务被创建并启动并返回Accepted(// 2)。但在这一点上,提琴手不显示202的结果。见所附图像:

http://imageshack.us/photo/my-images/703/fiddler1.png/

当慢任务结束,代码继续捕获退出码(// 4),然后将202被捕获到的Fiddler。

这很奇怪,因为很久以前我做了回报。我错过了什么?我怎样才能改变这个代码,以便快速返回一个202并忘记这个任务。

注意:我知道如何做到这一点与非框架4.5功能,我想学习如何使用async/await。

+1

我认为这是因为'runProcessAsync()'运行在请求的同步上下文中。如果你不想这样做,你可以使用'Task.Run(()=> runProcessAsync(id));'。但要小心,因为IIS可以在此期间回收您的appdomain,所以有可能'runProcessAsync()'不会完成。 – svick 2013-02-15 15:18:01

+0

我做到了,工作。这是一个遗憾,你没有给出正确的答案,因为你解决了我的问题 – Jordi 2013-02-18 09:02:57

回答

4

我认为这是因为runProcessAsync()在请求的同步上下文上运行。如果你不想要,你可以使用Task.Run(() => runProcessAsync(id));。但要小心,因为在那段时间IIS可以回收你的AppDomain,所以有机会runProcessAsync()不会完成。

1

最简单的方法是将runProcessAsync更改为返回Task。请记住,async方法应尽可能返回Task/Task<T>,并且只有当它们的时才返回void

但是,我必须告诫你,这是相当危险的。 ASP.NET是一个HTTP服务器,所以如果没有活动的请求,它会随时取消你的AppDomain,如果它想的话。这意味着你的“用exitcode做更多的事情”将会从地球上消失。

我有一个blog post with a BackgroundTaskManager,您可以使用它在ASP.NET运行时注册Task。如果有尚未完成的注册Task s,它将尝试延迟AppDomain关闭。但是,这只是一种“尽最大努力”。这种事情没有保证。在ASP.NET中运行的任何代码都与活动请求无关,这是一种危险的情况。

+0

我不明白,为什么要改变返回类型的'任务'帮助?如果问题出现在同步上下文中,那么这不会改变什么,不是吗? – svick 2013-02-15 23:08:13