2016-06-15 18 views
1

私はHostingEnvironment.QueueBackgroundWorkItemでアクションを実行していると言うthis documentation読んだ:HostingEnvironment.QueueBackgroundWorkItemは実際にリサイクルを遅延させますか?

が現在実行されているこのAPIを介して登録されたどのように多くの作業項目を追跡することができるASP.NETでの通常のThreadPool作業項目とは異なりますし、これらの作業項目の実行が完了するまで、ASP.NETランタイムはAppDomainのシャットダウンを遅延させようとします。このAPIは、ASP.NET管理のAppDomainの外部で呼び出すことはできません。提供されているCancellationTokenは、アプリケーションのシャットダウン時に通知されます。

だから私は、このサンプルコード書いた:

private void Check() { 
    HostingEnvironment.QueueBackgroundWorkItem(ct => CheckRecyclingBehaviour(ct));} 
} 

private async void CheckRecyclingBehaviour(CancellationToken ct) { 
    while (true) { 
    await Task.Delay(1000); 
    if (ct.IsCancellationRequested) { 
     AppendToFile("Recycling soon..."); 
     await Task.Delay(1000); 
     AppendToFile("But we still have time to finish..."); 
     break; 
    } 
    } 
} 

を私は(IIS 7上)check()を実行したと、しばらくして私は、IISマネージャを使用してリサイクルを余儀なくされました。

最後に、私はdebug.txtファイルをチェックしました。これには、 "リサイクルすぐ..."という1行が含まれています。

CancellationTokenは通知されましたが、AppDomain Shutdownは実際には遅延されませんでした(2回目の印刷が行われていないため)。

特に、私が読んだいくつかの投稿を考えれば、かなり奇妙に思えます。recycling will be delayed by 30 seconds

私に何か不足していますか?

答えて

3

あなたはasync voidを使用しています。これがあなたのことです。私がmy MSDN article on async best practices, you should avoid async voidで説明しているように。

async Taskasync voidを変更すると、正しく動作することがわかります。

詳細情報:それはasync voidメソッドの完了を検出するために、非自明なので、あなたがQueueBackgroundWorkItemに投稿されたコードは、実際に(最初awaitで)ほぼ即時に完了しました。 ASP.NETがシャットダウンすると、取り消しトークンが設定され(最初の行をファイルに同期して書き込む)、キューに入れられた作業がすべて待機されます。作業はすでに完了しているので、すぐにアプリケーションドメインを破棄し、残りのメソッドを破棄します。

async Taskメソッドを使用する場合、QueueBackgroundWorkItemは、タスクが完了するまでコードが完了していないことを理解します。

+1

実際には、それが完全に修正されるかどうかわかりませんが、間違っているかもしれませんが、強制的にリサイクルすると、「自然に起こった」ときだけ、QueueBackgroundWorkItemで実行中のタスクを尊重しないと思います。それを 'Task'に変更するとナチュラルリサイクルのために修正されますが、私はまだ強制リサイクルが同じように動作すると思います。 –

+0

ありがとう、私は 'タスク'に変更し、それは働いた。スコット、警告のためにありがとう、しかし幸いにも強制的なリサイクルは、実行中のタスクを尊重します。 – oavraham

関連する問題