2017-02-11 13 views
-2

潜在的に多くのプロセスで共有されるリソースがあり、使用しなくなったときにクリーンアップする必要があります。c#inter process取得/解放リソース数

プロセス間の使用回数を維持して、リソースが使用されなくなったときにクリーンアップできるようにする最も簡単な方法は何ですか?

(リソースを使用する最後のプロセスが終了した場合、使用する次のリソースが有効な使用回数を持つ限り、リソースは未処理のままにしておくことができます)。

+0

「リソース」は何を意味するものではありません、あなたは具体的にする必要があります。 –

+0

リソースは無関係です。リソースを作成するために実行される任意のシステムコマンドとそれを破壊するコマンドがあるとします。私はそれが使用中(クロスプロセス)に基づいて寿命を管理する必要があります。 – CoderBrien

+0

ライフタイムは、すべてのプロセスが終了すると終了します。したがって、基本的に解決策はありませんが、可能な限りすべてのプロセスを監視するマネージャーを作成してください(彼らはハートビートパケットを送信するか、pingを実行しても問題ありません)。このタスクにはWindowsサービスを使用できます。または、リソース内にセマフォーを作成し、それを減らす最後のプロセスを作成することができます。リソースを取り除きます。しかし、この方法は信頼できるものではありません。私はあなたのコンピュータをシャットダウンすることができます。そして、リソースは永遠に生き続けるでしょう。 – eocron

答えて

0

私が使用したコード:

internal sealed class InterProcessResource { 
    private static readonly string MutexNameThisProcess = "IPR-" + Guid.NewGuid().ToString(); 
    private static readonly Mutex MutexThisProcess = new Mutex(true, MutexNameThisProcess); 

    private readonly MemoryMappedFile mmf; 
    private readonly string mutexName; 

    public InterProcessResource(string resourceName) { 
     this.mutexName = resourceName + "-mtx"; 
     this.mmf = MemoryMappedFile.CreateOrOpen(resourceName + "-mmf", 16 * 1024, MemoryMappedFileAccess.ReadWrite); 
    } 


    public void Acquire(Action initAction) { 
     using (new Mutex(true, this.mutexName)) { 
      var currentList = ReadStringList(mmf); 
      if (currentList.Count == 0) { 
       initAction(); 
      } 
      var newList = PruneMutexList(currentList); 
      newList.Add(MutexNameThisProcess); 
      WriteStringList(this.mmf, newList); 
     } 
    } 

    public void Release(Action freeAction) { 
     using (new Mutex(true, this.mutexName)) { 
      var currentList = ReadStringList(this.mmf); 
      var newList = PruneMutexList(currentList); 
      WriteStringList(this.mmf, newList); 
      if (newList.Count == 0) { 
       freeAction(); 
      } 
     } 
    } 

    private static List<string> ReadStringList(MemoryMappedFile mmf) { 
     var list = new List<string>(); 
     using (var stream = mmf.CreateViewStream()) { 
      var reader = new BinaryReader(stream); 
      int count = reader.ReadInt32(); 
      for (int i = 0; i < count; i++) { 
       list.Add(reader.ReadString()); 
      } 
     } 
     return list; 
    } 

    private static void WriteStringList(MemoryMappedFile mmf, List<string> newList) { 
     using (var stream = mmf.CreateViewStream()) { 
      var writer = new BinaryWriter(stream); 
      int count = newList.Count; 
      writer.Write(count); 
      for (int i = 0; i < count; i++) { 
       writer.Write(newList[i]); 
      } 
     } 
    } 

    // removes our mutex name AND any dead processes mutex names 
    private static List<string> PruneMutexList(List<string> list) { 
     var newList = new List<string>(); 
     foreach (var s in list) { 
      if (s != MutexNameThisProcess) { 
       Mutex m; 
       if (Mutex.TryOpenExisting(s, out m)) { 
        newList.Add(s); 
        m.Dispose(); 
       } 
      } 
     } 
     return newList; 
    } 
} 
1

すべてのプロセスが同じマシン上にある場合は、インスタンスカウントを含むファイルを作成します。リソースがプロセスによってプロビジョニングされると、ファイルは書き込み用に開かれ、ファイルを効果的にロックする必要があります。インスタンスカウントを読み込み、インクリメントしてから、ファイルに対して書き込みロックを解放する必要があります。

プロセスが終了する(またはリソースで完了した)場合、ファイルへの書き込みロックを取得し、リソース数を減らします。リソースカウントが減少後にゼロである場合は、クリーンアップ手順を開始します。

ファイルが既に別のプロセスによって書き込まれている間に、2番目のプロセスが共有ファイルの書き込みロックを取得しようとすると、再試行ロジックが必要になります。

重要な点は、OSが排他的な書き込みロックを提供できることです。これは事実上クリティカルセクションです。

+0

それはアイデアですが、ハードプロセスの終了を処理しないので、より複雑になるようです(たとえば、PIDやシステムミューテックス名のリストを維持するなど)。うん。 – CoderBrien

+0

監視プロセスを作成するだけで、プロセスがひどく死んでもprocessCount = 0でクリーンアップされます。 – eocron

+0

ええ、それらのハード出口(誰かがプロセスを殺すか、電源コードを引っ張る)は対処するために吸うつもりです。私が見たもう1つの方法は、クリティカルセクションを持ち、ディスクにカウントをシリアル化し、RPCを使用してインクリメントまたはデクリメントする別々のアプリケーションを持つことです。このようなプロセスから定期的なポーリングを実装して、リソースを使用して登録されているすべてのプロセスがまだアクティブであることを確認することができます。それは長い時間だったので(私の記憶はあいまいです)、古いCOMコンポーネントの時代にも同じ問題がありました。私はそれが当時どのように解決されたかを思い出さない。 –

2

リソースのコンシューマが異なるマシン上にある可能性がある.net remotingで実装されたパターンについて説明しています。これは、リースをリフレッシュしていない場合に消費者を自動的にタイムアウトするライフタイムリースでバックアップされた、オブジェクトを明示的にリリースするように強制します。

これがすべて.netフレームワークに既にあることを考えれば、私はあなたのフレームワークを生成するためにリモーティングを使うことをお勧めします。

+0

いくつかのサンプルコードを共有してください。私は遠隔操作をあまり使わなかった。 – CoderBrien

+0

Remotingライブラリパターンは、(WCFに置き換えられた)かなり古いものですが、リソースのインスタンスを作成してリサイクルするためのファクトリと、生成されリースされたインスタンスを追跡するためにファクトリで使用されるレジストリと、リース満了時)および消費者が明示的に(メソッドコールを介して)リースまたはリースを更新する方法。 .netメモリキャッシュクラスを使用して、このリリース、更新、および有効期限の要素を簡単に実装できます。 – PhillipH

+0

これは本当に複雑に聞こえます。 10〜20行のコードを最大で見つけることを望んでいました。私はトリックを行うかもしれないと思うmemorymappedfiles/mutexesで刺す。 – CoderBrien

関連する問題