2

このメソッドExportTo3rdParty()を AsyncController を使用するように変換しようとしています。

public JsonResult SaveSalesInvoice(SalesInvoice invoice)
{
    SaveInvoiceToDatabase(invoice); // this is very quick 
    ExportTo3rdParty(invoice); // this is very slow and should be async
}

しかし、ExportTo3rdParty() メソッドは複数の場所で HttpContext.Current を使用します (変更するには多すぎる - 元のコーダーは依存性注入を十分に使用していませんでした)。たとえば、GetDefaultCurrency() を呼び出します。ExportTo3rdParty() が AsyncController を介して呼び出された場合、これは引き続き機能しますか?

public Currency GetDefaultCurrency()
{
    Currency currency;
    string key = string.Format("DefaultCurrency_{0}", 
                                HttpContext.Current.User.Identity.Name);
    currency = HttpRuntime.Cache.Get(key) as Currency;
    if (currency == null)
    {
        currency = LookupDefaultCurrency();
        HttpRuntime.Cache[key] = currency;
    }
} 

Thread.Start を使用すると、HttpContext.Current にアクセスできないことがわかっています。しかし、AsyncController はどうでしょうか。

4

1 に答える 1

5

では、なぜ Async コントローラーを使用したいのですか?

速くなると思いますか?何かが遅いからといって、非同期にする必要があるわけではありません。実際、スレッド管理/コンテキスト切り替えのオーバーヘッドが原因で、非同期で実行するとメソッドが遅くなる可能性が最も高いでしょう。

あなたが示した2つの方法から私が理解できることはほとんどありません。ExportTo3Party は基本的に「帯域外」で実行できると思います。それは外部プロセスによるものです。したがって、MSMQ を使用してジョブをキューに入れ (これはすぐに返されます)、ブロックされないようにする必要があります。そして、キューに入れられたジョブを他のプロセス/アプリケーションに処理させます。この他のプロセスは、(Task Sheduler を使用して) サーバー上で実行され続ける通常のコンソール アプリケーションである可能性があり、ジョブがキューに到着するとすぐにジョブを処理します。

または、さらに単純 (MSMQ を使用していない場合) は、単に外部アプリケーションを実行し (コンソール アプリをもう一度)、アプリが終了するのを待ちません。したがって、System.Diagnostics.Process を使用してプロセスを開始し、WaitForExit を使用しないでください。

これらの代替案は両方とも、ExportTo3rdParty が行っていると私が考えるものを実装するための正しい/より良い方法です。このメソッドからの応答を待っていないことがわかります。

まだ納得していない場合は、次のようにします。

MSDN ドキュメントから

非同期アクション メソッドが、BeginMethod/EndMethod パターンを使用してメソッドを公開するサービスを呼び出す場合、コールバック メソッド (つまり、非同期コールバック パラメーターとして Begin メソッドに渡されるメソッド) は、下にないスレッドで実行される可能性があります。 ASP.NET の制御。その場合、HttpContext.Current は null になり、アプリケーションが Parameters などの AsyncManager クラスのメンバーにアクセスするときに競合状態が発生する可能性があります。HttpContext.Current インスタンスに確実にアクセスできるようにし、競合状態を回避するために、コールバック メソッドから Sync() を呼び出して HttpContext.Current を復元できます。

コールバックが同期的に完了すると、ASP.NET の制御下にあるスレッドでコールバックが実行され、操作がシリアル化されるため、同時実行の問題は発生しません。既に ASP.NET の制御下にあるスレッドから Sync() を呼び出すと、未定義の動作が発生します。

ActionCompleted メソッドは、ASP.NET の制御下にあるスレッドで常に呼び出されます。したがって、そのメソッドから fSync() を呼び出さないでください。

Begin メソッドに渡すコールバックは、ASP.NET の制御下にあるスレッドを使用して呼び出される場合があります。したがって、Sync() を呼び出す前に、この条件を確認する必要があります。操作が同期的に完了した場合 (つまり、CompletedSynchronously が true の場合)、コールバックは元のスレッドで実行されているため、Sync() を呼び出す必要はありません。操作が非同期で完了した (つまり、CompletedSynchronously が false) 場合、コールバックはスレッド プールまたは I/O 完了ポート スレッドで実行されており、Sync() を呼び出す必要があります。

http://msdn.microsoft.com/en-us/library/ee728598.aspx

于 2011-02-20T06:49:55.913 に答える