2016-07-06 4 views
0

これらの2つの記事、SynchronisationContextおよびAsync/Awaitを読んでください。私はASP.NET SynchronisationContextが非同期メソッドの実行をリクエストスレッドに再入力する方法をよく知っています。ASP.NETで既定のThreadPool SynchronisationContextを使用する

再入国の大きな問題の一つは、あなたが.Wait()を使用するか、または.Result場合は、デッドロックを引き起こす可能性があることである、なぜ:のawaitが完了すると

、それは非同期メソッドの残りの部分を実行しようとしキャプチャされたコンテキスト内でしかし、そのコンテキストには既にスレッドがあり、非同期メソッドが完了するのを(同期的に)待機しています。

あなたは理由SynchronisationContextとTask.Factory.StartNewを使用し、それをASP.NETアプリケーション内ThreadPoolSynchronisationContextを割り当てる場合の影響がどうなるか、それはpermits only one chunk of code to run at a time.

方法で使用されているシングルスレッドのこれを取得?

私はあなたがこれをやる理由に悩まされません。何が起こるのでしょうか?

非同期操作が完了する前にスレッドがクリアされる可能性があるため、ASP.NETで非同期操作をFire-and-Forgetすることは決してありません。 ThreadPoolSynchronisationContextの場合も同様です。

答えて

1

Task.Factory.StartNewを使用してASP.NETアプリケーション内でThreadPool SynchronisationContextを割り当てることの意味は?

StartNewを使用する理由はありません。 Task.Runはほとんどすべての使用例で優れています。また、スレッドプールのスレッドが自然にそれを持っているので、スレッドプールSynchronizationContextを「割り当てる」必要はありません。 (リクエストのコンテキスト外)スレッドプールのスレッドで実行されます

await Task.Run(async() => { ... }); 

とあなたの...コードのすべてを、そして(スレッドプールのスレッド上で再開:

ので、必ず、あなたははこれを行うことができます要求コンテキスト外)。

私たちのコードはawaitの結果であるため、この使用法では火災や忘れの問題は発生しません。それはやっているかについて考えるため

しかし、私は一般的に、ASP.NETでこれを思いとどまら:

  • コードキューは、スレッド・プールに(...)働きます。
  • 次に、非同期にその作業が完了するまで待機します。この間、元の要求スレッドはスレッドプールに返されます。
  • 作業が完了すると、呼び出し元のメソッドは要求コンテキストで処理を続行します。

このようにすると、余計なスレッド切り替えが発生しますが、何のメリットもありません。の並列性はわずかですが、潜在的に深刻なスケーラビリティの制限について話しています。本番環境でASP.NETで並列処理を行うたびに、私はそれをリッピングしてしまいました。

非同期操作が完了する前にスレッドがクリアされる可能性があるため、ASP.NETで非同期操作をFire-and-Forgetすることは決してありません。これは、ThreadPool SynchronisationContextの場合にも当てはまりますか?

実際には、特定のスレッドが異常終了したためではありません。これはAppDomain全体が解体されたためです。これには、すべてスレッドが中止されます。

だから、はい、ASP.NETには、ファイア・アンド・フォーゲットスレッドプールを使用したが、ファイア・アンド・フォーゲットの他の種類と同じくらい悪いです:

Task.Run(() => ...); // bad! 

非常に少なくとも、あなたはではなく、という単語を実際の意味で信頼できるものにします。は、作業が中止される可能性を最小化する)をASP.NETランタイムに登録する必要があります。現代のASP.NETはHostingEnvironment.QueueBackgroundWorkItemです。

ASP.NETがこのメソッドを追加する前に、私は非常によく似た方法で仕事を登録したライブラリを持っていました。 I used Task.Runは、登録された作業を任意の要求コンテキストの外部で実行し、スレッドプールSynchronizationContextを使用して実行します。

+0

したがって、残りの作業を実行する同期コンテキストがまだ一度に1つずつ実行されているので、 'Task.Run'で' .Result'と '.Wait()'を呼び出す効果は同じですそれはASP.NETのコンテキストであるので –

+0

私は 'Task.Run'はキャプチャされたコンテキストを使用すると思ったが、私は[ソースコード]から見ることができる(http://referencesource.microsoft.com/#mscorlib/system /threading/Tasks/Tasks/Task.cs,89fc01f3bb88eed9)[ThreadPoolTask​​Scheduler](http://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/TaskScheduler.cs,495c69a13f3b023f) –

+0

@CallumLinington:あなたがブロックした場合タスクが 'Task.Run'から返された場合、リクエストコンテキスト内のスレッドをブロックします。その作業は1つではなく2つのスレッドを使用しています。 –

関連する問題