2012-04-13 9 views
2

私たちは、 "高価な作成"データを読み込んでキャッシュする大量の.Net 3.5アプリケーションを使用しています。アプリケーションは、「別のプロセスで使用されていません」に基づいてファイルを読み取り、書き込みます。他のプロセスがファイルを読み書きしている場合、アプリケーションはスリープ状態に移行してから再試行します。これはファイルを読み書きする正しい方法ですか?お知らせ下さい。ファイルへの書き込みの正しい正しい方法:頻繁に使用されるアプリケーション

public void Add<T>(string key, CacheItem<T> item) 
     { 
      bool fileInUse = false; 
      while (!fileInUse) 
      { 
       try 
       { 
        using (Stream stream = new FileStream(Path.Combine(cachePath, key+".bin"), FileMode.Create, FileAccess.Write, FileShare.None)) 
        { 
         Serializer.NonGeneric.Serialize(stream, item); 
        } 
        fileInUse = true; 
       } 
       catch (IOException ex) 
       { 
        if (ex.Message.Contains("being used by another process")) 
        { 
         //Poll till the file is free to be used by this process 
         Thread.Sleep(100); 
         fileInUse = false; 
        } 
       } 
      }    
     }   

public CacheItem<T> Get<T>(string key, Type type) 
     { 
      CacheItem<T> item = null; 

      FileInfo fileInfo = new FileInfo(Path.Combine(cachePath, key+".bin")); 
      fileInfo.Refresh(); 
      if (fileInfo.Exists) 
      { 
       bool fileInUse = false; 
       while (!fileInUse) 
       { 
        try 
        { 
         using (Stream stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.None)) 
         { 
          object objectTemp = Serializer.NonGeneric.Deserialize(type, stream); 
          item = (CacheItem<T>)objectTemp; 
         } 
         fileInUse = true; 
        } 
        catch(IOException ex) 
        { 
         if (ex.Message.Contains("being used by another process")) 
         { 
          //Poll till the file is free to be used by this process 
          Thread.Sleep(100); 
          fileInUse = false; 
         } 
        } 
       }    
      }      
      return item;         
     } 

答えて

2

あなたは絶対的に必要以上に待っ避けるために、その上にグローバルミューテックスを追加することができます。

グローバルミューテックスは、空でないnameMutex Constructorに渡すことで作成されます。

利点:

  • ミューテックスはファイルではなく、平均で50ミリ秒を待つので、利用可能になった後、すぐに目を覚ますことができます。
  • ミューテックスでは、睡眠/覚醒を繰り返す代わりに、を一度にに、起床してに、を1回ずつ寝返らせることができます。スリープしているスレッドは、OSによって非常に効率的に処理され、リソースをほとんど消費しません。
  • ミューテックスを取得すると、成功する前に潜在的に何度も失敗するのではなく、ほぼ100%成功する可能性があります。すべてのすべてで

、あなただけの速くするつもりされていない、あなたは少ないCPUサイクルプロセスにおけるをおそらく消費します。

+0

上記のコードに必要な変更を加えてもよろしいですか? – Pankaj

+2

@PankajGarg私はできると確信していますが、それは何を達成するでしょうか?この仕組みがどのように機能するのか不明な点はありますか? –

+0

Branko; は、ここに私たちの建築家の一人は=>述べ何である「私はミューテックスクラスを使用して持って予約をそれが私たちのパフォーマンスの向上の目的を破っロックステートメントを使用するか、クラスを監視するよりも計算に高価であるということです。」何かご意見は? –

1

これはたくさんのことをしているので(パフォーマンスが問題になる)、私は別のデザインを提案します。

文字列(複数のファイルで動作する場合はファイル名)をとるパブリック静的メソッド(またはシングルトンのメソッド)が必要です。そのメソッドでは、その文字列をBlockingCollection<string>に配置する必要があります。 (Dictionary<string, BlockingCollection<string>>を使ってファイルごとに1つずつ、またはそのファイルのキューにファイル名をマップすることで1つのファイルにすることができます)。

大部分の場合ファイルに追加するだけでキューに追加してから、作業に戻ります。

ブロッキングコレクションから読み込んだスレッド/タスクを別に持つ必要があります(ブロッキングコレクションがたくさんある場合でも必要です)。そして、データをファイルに書き出します。ファイルに書き込むスレッドは1つしかないので、ファイルIOを周回する必要があるロックはなく、BlockingCollectionはこのプロデューサ/コンシューマモデルで動作するように設計されており、必要なロックをすべて処理します。

複数のキューを処理しようとすると魅力的なパフォーマンス上の理由が見つからない限り、すべてのファイルに単一のBlockingCollecitonを使用することをお勧めします。それはかなり簡単に管理するでしょう。

+0

Thanks Servy。私は、私たちのアプリケーションが.Net 3.5アプリケーションであることを追加することを忘れていました。 BlockingCollectionは.Net 4.0の一部です。 –

+0

@AjitGoel代わりに 'ConcurrentQueue'を使ってすべてを行うことができます。ちょっと便利ではありませんが、できます。 – Servy

+0

ConcurrentQueueは.Net 4.0以上ですか?私は私たちのアプリケーションで使用することはできません。 –

関連する問題