PreApplicationStartMethod
属性によって装飾されたアセンブリ内のクラスのメソッドは、Application_Start
イベントが発生する前に呼び出されることを意図しています。たとえば、これはBuildManager
、ページ、コントロール、またはビューをコンパイルするときに、どのアセンブリ (Web アプリケーション内のアセンブリに加えて) を参照するかを知る方法です。
指摘されたメソッドが 1 回だけ呼び出されることを期待するのはごく自然なことです。結局のところ、これは初期化プロセスの一部であり、通常はアプリケーションごとに 1 回だけ実行されます。(データベースを 2 回作成する試みについてのみ言及します!!)
いくつかのトレース呼び出しを追加した後、メソッド (常にではなく、時々!) が 2 回呼び出されていることがわかりました。これを避けるために、クラスにブール値フィールドを追加して、次のような複数の呼び出しを防ぎました。
private static bool initialzed;
public static void Initialize()
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
驚いたことに、このメソッドは再び 2 回呼び出されました。明らかな疑いは、2 つの異なるスレッドで呼び出されたということでした (初期化コードでは少し意味があるにもかかわらず)。 ダブルチェック ロックは、このような問題に対する明らかな解決策でした。そのため、コードを次のように変更しました。
private static readonly object SyncRoot = new Object();
private static bool initialzed;
public static void Initialize()
{
if (PreApplicationInit.initialzed == false)
{
lock (PreApplicationInit.SyncRoot)
{
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
}
}
これを実際に問題にしているのは、コードがネイティブ コードから呼び出されるという事実です。これは、トレースポイントからの $CALLER です。
[Native to Managed Transition]
だから、私の質問は明らかです、私は推測します: 何 (そしてもっと重要な理由!Application_Start
) は、イベントの前に複数回呼び出されるように指定されたメソッドを呼び出しますか?