繁体   English   中英

MVC4 WebApi进程启动器

[英]MVC4 WebApi process launcher

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

我的代码看起来像:

[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;
    }  
}

理想情况下,有人会使用POST动词执行api休息调用(/ task / slowtask / launch),并期望202(接受)非常快。

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

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

当慢速任务结束时,代码继续捕获exitcode(// 4),然后202被捕获到Fiddler中。

这很奇怪,因为很久以前我做过回归。 我错过了什么? 如何更改该代码以便非常快速地返回202并忘记该任务。

注意 :我知道如何使用非框架4.5功能,我正在尝试学习如何使用async / await。

我认为这是因为runProcessAsync()在请求的同步上下文上运行。 如果您不想这样,可以使用Task.Run(() => runProcessAsync(id)); 但请注意这一点,因为IIS可以在此期间回收您的AppDomain,因此runProcessAsync()可能无法完成。

最简单的方法是只更改runProcessAsync以返回Task 请记住, async方法应尽可能返回Task / Task<T> ,并且只在必要时才返回void

但是,我必须提醒你,这是非常危险的。 ASP.NET是一个HTTP服务器,因此如果没有活动请求,它可以随意删除您的AppDomain。 这意味着你“用exitcode做更多的东西”只会从地球上掉下来。

我有一个带有BackgroundTaskManager博客文章 ,您可以使用它来向ASP.NET运行时注册Task 如果已注册的Task尚未完成,它将尝试延迟AppDomain关闭。 然而,这只是“尽力而为”; 这种事情无法保证。 在ASP.NET中运行的任何与活动请求无关的代码都是危险的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM