2010-12-07 18 views
3

確実に動作するかどうかわからないモデルを使用していると思われるアプリケーションの半分を継承しました。ASP.NET WebサービスからステートフルアンマネージドC++クラスを呼び出す

それが呼び出しごとに

[DllImport ("kernel32.dll" , EntryPoint = "LoadLibraryA")] 
public static extern int LoadLibrary(string lpLibFileName); 

を使用して管理されていないC++ .DLLをロードした後、例えば、それにコールの数を行いASP.NETのWebサービスでありますアンマネージC++で

[DllImport(@"MyUnamanagedDLL.dll")] 
public static extern string DoStuff(); 

コールの間状態を保持するためにシングルトンを使用している.dllを。これは、あまりにも遅いので、各Webサービス呼び出しではなく、ディスクとデータベースから1回だけ初期化して一連の低速処理をロードするだけです。

したがって、インスタンスがnullの場合、アンマネージ.dllが最初にGetinstance()を呼び出すと、インスタンスが初期化され、すべてのインスタンスがリロードされます。

webserviceで毎回FreeLibraryが呼び出されていないため、アンマネージクラスを毎回再初期化する必要があると考えられます。

このモデルはすべて信頼性がありますか? Webサービスがシャットダウンされ、アンマネージ状態が適切にクリーンアップされることを保証できますか? loadlibrary呼び出しの間に有効なシングルトンインスタンスを取得できるかどうかを確認できますか?

+1

プロのヒント:これがシングルトンが悪い理由です。 – Puppy

答えて

0

アンマネージドDLLを使用して読み込みが必要な理由がわかりません。あなたが何をしているのかわかっていて、それがどうしているのかわからないのであれば、アンマネージドdllの中のオブジェクトがデストラクタと適切なメモリ管理を持っているかどうかは常に疑う必要があります。

dllが何を達成しているか分かっていて、それをC#で書くのにあまり努力していないのであれば、ASP.NETのセッション状態を使って各セッションの呼び出し間にデータを格納できます。

.NET 2.0では、global.asaxはデフォルトでWebサービスのアプリケーションに追加されませんが、手動で追加することはできません。 WebサービスアプリケーションはまだWebアプリケーションです... global.asaxを使用しないと、各サービス呼び出しによってサービス呼び出しの間、固有のsessionidが生成されます。追加すると、その間に情報を保持できます。あなたが遅いデータの取得を行うコードを追加、などできるのGlobal.asaxのSESSION_START方法で

protected void Session_Start(object sender, EventArgs e) 
{ 
    Trace.WriteLine("Session_Start"); 
} 

(アンマネージドDLLと同等のものを...)。また、そのデータをセッション自体に格納することもできますし、データを保持するglobal.asaxに静的変数を作成することもできます。(非管理対象DLLのシングルトンと同じように)

+0

こんにちはBleeptzer、管理されていないDLLはRPCコールを作成し、残念なことに.NETに移行するのは簡単ではない多くのレガシーコードとあらゆる種類のものを使用します。 – Terry777

1

このモデルはまったくですか?信頼性のある? Webサービスがシャットダウンされ、アンマネージ状態が適切にクリーンアップされることを保証できますか?

答えはいくつかによって異なります。まず第一に、どのような国家ですか?メモリ、ファイルハンドル、HWNDs、そしてyou can expect the kernel to clean up when the library is unloadedのような、カーネルが根本的に責任を負うものを見ているなら、それはいつでも(私はゴールドリンカーです。私は意図的にデストラクタを省略します。このような場合、デストラクタはプログラムの終了を遅らせる役割しか果たしません」と、私は金のリンカーがWindows上で動作しないことを知っていますが、原則はそのまま適用されます)。

カーネルによって保証されていないものについては、DllMain機能を提供して、PROCESS_DETACHメッセージを処理して必要なアンロードを処理することをお勧めします。

loadlibrary呼び出し間で確実に有効なシングルトンインスタンスを確実に取得できるかどうかを確認できますか?

やすい場合がある。

  • シングルトンは、Aは、プロセスBは、シングルトンを必要とし、それが既に存在している見て、それ
  • を使用
  • それを、シングルトンを必要作成し、使用
  • プロセス存在しません
  • プロセスAとBはシングルトンを必要としなくなりましたが、これはクリーンアップされました
  • シングルトンは存在しません
  • プロセスCは、より困難なケースが作成またはクリーンアップにレースの条件のいずれかを伴うだろう...

それを、シングルトンを必要と作成し、使用しています:

  • シングルトンは
  • プロセスは存在しません。シングルトンを必要とし、それを作成し始めます。
  • プロセスAが終了する前に、プロセスBはシングルトンを必要とします。これは問題です
  • プロセスAとBはもはやシングルトンを必要とせず、クリーンアップを開始します
  • シングルトンがクリーンアップされる前に、プロセスCはそれを必要とし、それが存在すると見てそれを使用しようとします。これは問題です

これは古典的な競合条件です。解決策はチェック/作成ステップ(およびチェック/クリーンアップ)がアトミックであることを確認することです。空想を得ないでください。 atomic参照カウントまたはMutexes


は、記録のために使用します。私はこの種のアーキテクチャのファンではありません(図書館のシングルトン)。代わりに問題の状態がオブジェクトに格納されているライブラリをお勧めします。ライブラリAPIは、APRに似たCのようなもの(エクスポートされた関数、CreateXxxObject()/ DestroyXxxObject()関数、またはに似ている)、またはC++のようなものになります。シングルトンモデルがそれをカットしない時が来るでしょう。

しかし、私は唯一の「あなたの計画を捨て、最初の...」と言っていない、尋ねた質問に答えるよ

0

を私はできたレガシー管理されていないDLLでの作業は数年前に同様の問題に直面しましたアップグレードすることはできません。問題は、Webサーバーの内部でP/Invokeを使用することで再生したくないということです(なぜか分かりませんが、セキュリティ上の問題であったと思います)。私がしなければならなかったのは、WindowsサービスのDLLへの呼び出しをラップし、WCFリモート呼び出しを使用して相互運用性を偽装することでした。残念ながら、私はもはやそのコードにアクセスすることはできませんまたは私はあなたに良いサンプルを提供するだろう。私はこれが正しい方向に向けることを願っています。

0

私は最近、非常に似たプロジェクトを開発しました。私の場合は、COM +を使用するアーキテクチャとp/Invokeを使用するアーキテクチャがあります。シンプルさのためにp/Invokeメソッドを選択しました。私は、これはMicrosoftを含む不正確なアプローチだと多くの人が私に明らかに教えてくれました!結局、私は頭痛の多いp/Invokeアーキテクチャを使用することができましたが、そこに入るのは簡単ではありませんでした。ヒープとスタック、メモリ割り当て、バッファ/スタックの問題の上書き、ASP.Netセキュリティの問題、とりわけ管理コードと非管理コードのアーキテクチャ上の違いなど、管理対象データ構造と非管理対象データ構造の違いに対処する必要がありました。結局、脳の痛みは私にとってはるかに優れたプログラマを残しました。

アンマネージドクロス言語DLLは、p/Invokeを使用してマネージコードからre-entrantly呼び出すことができますか?はい、できます。しかし;再入可能な状態で状態を維持するように設計する必要があります。つまり、アンマネージDLLは、割り当てられたメモリを追跡し、Webサービスから呼び出されるたびにそのメモリを解放する必要があります。別のWebサービス呼び出しに属するメモリを解放したり、割り当てたりしてはいけません。

関連する問題