6

私はいくつかのリードを得るために同様の問題を見つけるのに本当に苦労しましたが、私たちが抱えているケースについて誰も説明していないようです.

バックグラウンド

次の一般的な設計の製品があります。

【ローカルインストールフォルダ】

  • 製品機能の大部分を実装する .NET アセンブリのセットが含まれています。
  • 例:実装 1.dll実装 2.dll

【GAC】

  • ClientAPI.dll。エンド ユーザーの Visual Studio プロジェクトから参照されるクライアント アセンブリ。ローカル インストール フォルダー内の実装 dll への強力な参照があります。

ClientAPI.dll には、エンド ユーザー プロジェクトを呼び出す必要があるエントリポイントがあります。と呼びましょうInitialize()

最初に行うことは、イベントを使用して、Initializeいわゆるアセンブリ解決ハンドラーを現在のドメインにインストールすることです。AssemblyResolveこのハンドラーは、.dll を使用して、実装 dll を見つけてクライアント プロセスにロードする方法を認識しますAssembly.Load()

コンソール アプリケーションを考えてみましょう。次のようになります。

class Class1
{
    void Main(string[] args)
    {
        ClientAPI.Initialize();

        // Use other API's in the assembly, possibly internally referencing the
        // implementation classes, that now will be resolved by our assembly
        // resolve handler.
    }
 }

これで、コンソール/Windows フォーム/WPF の世界ですべてがうまくいきました。アセンブリ解決ハンドラーが適切にインストールされて呼び出され、ClientAPI.dll が機能を要求すると、実装 DLL への参照を正常に解決できます。

問題文

そうは言っても、コンソールまたは WPF アプリケーションのみをサポートするつもりはないため、ASP.NET で同じ設計に依存していました。したがって、VS 2010 で新しい ASP.NET Web アプリケーション プロジェクトを作成すると、すべてが次のように簡単になると考えました。

class Globals : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        ClientAPI.Initialize();

        // ...
    }
}

ASP.NET ランタイム ユニバースに 20 ~ 30 時間滞在し、開発サーバーと IIS の両方で上記のことを試してみると、実際には期待どおりではないことがわかりました。

ASP.NET では、ClientAPIクラスがどこかで参照されるとすぐに、他のアセンブリへのすべての参照が即座に解決されることがわかります。それだけではありません。結果はキャッシュされます (.NET 2.0 以降は設計によるものです)。これは、CLR を支援しようとする機会がまったくないことを意味します。

私たちが試して学んださまざまなことについて詳しく説明することなく、基本的に次の質問に行き着きます。

ASP.NET がこのような参照を解決するのはなぜですか? 他のタイプのアプリケーションが行う方法とは互換性がありません。さらに、外部タイプ/アセンブリへの参照が最初に必要になったときに解決されるように指定されている.NET / CLRランタイムのドキュメントに従っていません(つまり、コードで最初に使用されます)。

どんな種類の洞察/アイデアも高く評価されます!

4

1 に答える 1

0

Windowsフォーム/WPFアプリケーションは個々のクライアントマシンで実行されます(したがって、単一のローカルコンテキストで実行されます)が、ASP.NetはIIS内、アプリケーションプール内、サーバーまたはサーバーのセット(Webファームの状況)で実行されます。アプリケーションプールにロードされたものはすべて、アプリケーション全体で使用できます(したがって、アプリケーションに接続するすべてのクライアント間で共有されます)。

HttpApplication.Application_Startは、アプリケーションの起動時に1回実行されます。Winformsアプリケーションの場合のように、クライアントごとに実行されるわけではありません。接続するすべてのクライアントに対して何かを初期化する必要がある場合は、Session_StartまたはSession_OnStartを使用しますが、クライアントの数によっては、サーバーのメモリの問題が発生する可能性があります。 Webアプリケーションに接続します。これは、クラスがシングルトンであるかどうか、およびInitialize()メソッドが静的であるかどうかにも依存します。これらの状況のいずれかが発生した場合は、クロススレッドの問題がかなり早く発生します。

さらに、アイドル状態のIISアプリケーションプールは、しばらくすると自動的にリセットされることに注意してください。たとえば、誰もWebアプリケーションを一晩使用しない場合、IISはアプリケーションのアプリケーションプールをフラッシュし、メモリを解放します。これらの設定はIIS管理内で変更できますが、変更する場合は注意が必要です。これらの設定を変更して、不適切に設計されたオブジェクト(またはWebアプリケーション用に設計されていないオブジェクト)を回避すると、さらに多くの問題が発生する可能性があります。

参考までに-私は少しうるさいですが、誤解を避けるために、オブジェクトはキャッシュされません-はい、それはメモリにロードされますが、メモリの管理方法はオブジェクトの設計方法(キャッシュ)に依存しますWebの世界ではまったく別のものであり、アプリケーションのさまざまなレイヤーに実装できます)。

WebアプリケーションをWindowsアプリケーションのように動作させようとしないでください。あなたは自分自身により多くの問題を生み出すでしょう!

于 2012-02-10T13:57:06.347 に答える