为什么异步运行进程会阻塞线程?

时间:2016-06-13 16:16:44

标签: c# asp.net-mvc iis asynchronous

基于this answer,我有以下ASP.NET Action,它应该异步运行一个进程。但是,当我发出多个并行请求时,每个请求只在前一个请求完成后运行。为什么会这样?

    public async Task<ActionResult> Index(string url)
    {
        var exePath = Server.MapPath("~/App_Data/dummy/bin/dummy.exe");
        var startInfo = new ProcessStartInfo
        {
            FileName = exePath,
            Arguments = url,
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        };
        var process = new Process{ EnableRaisingEvents = true, StartInfo = startInfo};

        var tcs = new TaskCompletionSource<Process>();
        process.Exited += (sender, a) =>
        {
            tcs.SetResult(process);
        };
        process.Start();

        await tcs.Task;

        // todo: return process status/output
        return View();
    }

MVC Action中调用的进程dummy.exe的代码是:

class Program
{
    static void Main(string[] args)
    {
        Thread.Sleep(5000);
        Console.WriteLine("Hello world!");
    }
}

1 个答案:

答案 0 :(得分:1)

这里可能发生了两件无关的事情。

首先,async不会做你最有可能想到的事情,至少在Web应用程序的上下文中是这样。在操作内的所有工作完成之前,操作无法返回响应。它是异步的事实并没有让它更快地返回。相反,它只允许运行操作的线程在处于等待状态时返回到池中。然而,即使这样,线程也必须真正等待。运行进程是受CPU限制的,因此这里的异步操作基本上会同步运行,因为它需要线程来运行该进程。

其次,您最有可能在Visual Studio中的IIS Express中对此进行测试。 IIS Express是单线程的,因此意味着所有进一步的请求将被阻止,直到第一次完成。因此,除非您在完整的IIS(多线程)中运行此命令,否则将始终以串行方式处理请求。