2016-06-13 4 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

おそらく2つの無関係のものがここで起こってあります。

まず、asyncは、少なくともウェブアプリケーションのコンテキストで、あなたが思うように、ほとんどそうは思わないでしょう。アクション内のすべての作業が完了するまで、アクションは応答を返すことができません。それが非同期であるという事実は、それがより速く戻ることはありません。むしろ、単にアクションを実行しているスレッドを待機状態にしてプールに戻すことができます。しかし、それでもなお、スレッドは本当に待たなければなりません。プロセスの実行はCPUバウンドなので、ここでの非同期アクションは本質的に常に同期的に実行されます。プロセスを実行するスレッドが必要なためです。

第2に、Visual Studio内のIIS Expressでこれをテストする可能性が最も高いです。 IIS Expressはシングルスレッドなので、すべての要求は最初の完了までブロックされます。したがって、これをマルチスレッドのフルIISで実行している場合を除き、リクエストは常に、シリアルに関係なく処理されます。

+0

IISでテストしました。どのようにプロセスがCPUにバインドされているかについて詳しく説明していますが、 'WaitForExit()'を呼び出すのはそうではありませんか? – makhdumi

関連する問題