3

WCF サービスに接続する ASP.NET MVC 3 サイトがあります。WCF サービスはサイトから独立しており、Windows サービスでホストされています。ほとんどの呼び出しは同期的であるため、WCF がそれを実行するのを待つことは問題ではありません。

ただし、これらの (既に実装されている) 呼び出しの 1 つは少し時間がかかりすぎます。また、基本的に直接何も出力しないため、サービスでスピンして忘れたいと思いました。

だから私は自分のコードを次のように変更しました:

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  WcfServiceProxy.DoSlowCalculation(calculationOptions);
  ViewBag.Started = true;
  return View();
}

public ViewResult StartSlowCalculation(CalculationOptions calculationOptions)
{
  Task.Run(() =>
  {
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

  ViewBag.Started = true;
  return View();
}

私が理解しているように、これは非同期リクエストを開始し、すぐに戻る必要があります。それでも、実行は完全に同期的であり、UI は操作が完了するまで凍結されます。

私が見逃している明らかなことは何ですか?


アップデート:

また、呼び出しサイトでサービスへの呼び出しを同期解除するためだけに、サーバーの実装を非同期のものに変更したくないことに注意してください。

StartSlowCalculationさらに、メソッドの実行が終了しても、サーバーはサービス メソッドの実行が終了するまで応答を返さないことに気付きました。

WCF サービス プロキシは次のことを行います。

public void DoSlowCalculation(CalculationOptions calculationOptions)
{
   //some logging code
   Channel.DoSlowCalculation(calculationOptions);
}

したがって、完全に同期していますが、独立したスレッドで実行する必要があるため、問題にはなりません。

4

2 に答える 2

2

タスク操作は呼び出し元のスレッドで実行できますが、それは taskScheduler の決定に依存します。TaskScheduler長時間実行される呼び出しに関して正しい決定を下すために、タスク作成オプションを指定できますTaskCreationOptions.LongRunning

また、タスク操作が別のスレッドで実行されているかどうかを確認できます。

int launchedByThreadId = Thread.CurrentThread.ManagedThreadId;
int launchedInThreadId = -1;
Task.Run(() =>
  {
    launchedInThreadId = Thread.CurrentThread.ManagedThreadId;
    WcfServiceProxy.DoSlowCalculation(calculationOptions);
  });

// then compare whether thread ids are different

ところで、あなたは何らかのTask.Wait()操作を使用していますか?スレッドの呼び出しもブロックします。

編集:

次の投稿が興味深いかもしれませんIs Task.Factory.StartNew() Guarantee to use another thread than the calling thread?

したがってTask.Factory.StartNew()、キャンセルトークンが必要ない場合でもキャンセルトークンを使用して指定してみてください。奇妙に聞こえますが、これにより、呼び出し元のスレッドでタスクが最終的に実行されないことが保証されるようです。私が間違っている場合は修正してください。

于 2012-12-27T11:32:30.633 に答える