2016-06-13 120 views
0

基於this answer,我有以下ASP.NET應用程序異步運行進程。但是,當我做出多個並行請求時,每個請求只在前一個請求完成後才運行。爲什麼會發生?爲什麼異步運行進程阻塞線程?

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(); 
    } 

dummy.exe的代碼,堪稱MVC行動的過程,就是:

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

隨機猜測 - 會話狀態鎖定? –

+0

@RenéVogt:這裏的'Main'方法是程序上面調用的方法的一部分,而不是其他方法。這裏的方法是一個MVC動作,所以它被稱爲請求管道的一部分。 –

+0

@ChrisPratt thx,我的壞... –

回答

1

有可能是兩個不相干的東西會在這裏。

首先,異步不會做你最可能認爲它的事情,至少在Web應用程序的上下文中。在動作完成之前,該動作不能返回響應。這是異步的事實不會讓它返回更快。相反,它只允許運行該操作的線程在處於等待狀態時返回到池。然而,即使如此,線程也必須真正等待。運行一個進程是CPU限制的,因此這裏的異步操作本質上會始終同步運行,因爲它需要線程來運行進程。

其次,您很可能在Visual Studio中的IIS Express中測試此功能。 IIS Express是單線程的,所以這意味着所有進一步的請求將被阻塞,直到第一次完成。因此,除非您在完整的IIS(多線程)中運行此操作,否則請求將始終按順序處理。

+0

我在IIS中測試過。詳細說明如何運行進程是CPU綁定的嗎?如果我調用'WaitForExit()',那不是唯一的情況嗎? – makhdumi