0

ビジネスケース:

リモートディレクトリからファイルをASMX web serviceコピー/削除/ダウンロードするがあります。MyWebMethodは、これらすべての操作を実行するビジネス クラスのインスタンスを作成します。ダウンロードの場合、どのファイルが最新かを確認してダウンロードします。ダウンロードしたらすぐに削除したいです。ただし、マルチスレッドのシナリオでは、削除しようとしているファイルが他のスレッドによって既に削除されている可能性があります。

私の解決策:

このような問題を回避するために、一度に 1 つのスレッドのみを Web サービスで実行したいと考えています。へのその他の呼び出しは、WebMethod前のスレッドがダウンロードおよび削除操作を完了するまで待機する必要があります。

このためstaticに、ビジネス クラスで 1 つの変数を宣言しました。WebMethodビジネス クラスのビジネス メソッド ( から呼び出される) の開始時に、lockこの静的オブジェクトで を呼び出します。lockしたがって、他の Web サービス呼び出しは、その静的変数 (オブジェクト) が解放されない限り、ビジネス メソッドのコードを実行しません。

 public class FileOperator
{
    private static object locker = new object();

    public void DownloadAndDeleteFile(string fileName)
    {
        lock(locker)
        {
            // All business logic goes here.
        }
    }
}

のコードは次のWebMethodようになります。

FileOperator fileOperator = new FileOperator();
        fileOperator.DownloadAndDeleteFile("File1.txt");

質問:

  1. 私の解決策は正しいですか?
  2. はいの場合、Web サービス内から 1 つのスレッドのみを実行できるようにするにはどうすればよいですか? 私はこれをダウンロードのためにのみ行いたいことに注意してください..アップロードは並列スレッドで動作するはずです..
  3. より良い解決策はありますか?

.NET 4.0 を使用しています。

4

3 に答える 3

2

以下は、あなたの要件についての私の理解です。

  • 複数のクライアント/スレッドがWebメソッドを実行しています。このメソッドは、リモートサーバーからファイルをダウンロードし、ダウンロード後に、ダウンロードしたファイルをリモートサーバーから削除します。

  • これで、さまざまなスレッドが同じファイルまたは異なるファイルをダウンロードする可能性があります。

  • 現在の実装の問題は、関数レベルで汎用ミューテックス(ロック)を使用しているため、スレッドが他のスレッドからアクセスされていないファイルをダウンロードしたい場合でも、別のスレッドが機能している間待機する必要があることです。別のファイルでは、要件に関係なくすべてのクライアントが同期されるため、システムをスケーリングするとパフォーマンスが大幅に低下します。

リモートサーバーでアクセスされるファイル/リソースに基づいてロックが存在する可能性がある回線で考えられる解決策について考えています。次の行を考えてください。

  • サーバーメソッドでは、静的オブジェクトのリストを維持します。各オブジェクトは異なるファイル/リソースに割り当てられ、作成された静的オブジェクトをファイルにマップするディクショナリを維持できます。スレッドにファイル名が付いている場合、関連するオブジェクトを取得します。既に存在する場合は、新しいオブジェクトを作成します。これで、そのオブジェクトのロックを取得しようとし、それが最初のスレッドである場合はアクセスを取得します。それ以外の場合は、別のスレッドが同じオブジェクトで作業している場合は待機する必要があります。関数内では、先に進むか、ミューテックスをすばやく終了する前に、まずファイルが存在するかどうかを確認できます。

  • すべてのスレッドのディクショナリオブジェクトの神聖さを維持するために、非常に短い期間、すべてのスレッドに有効な汎用ロックがあります。そのため、各スレッドはファイルの存在を確認できます

//大まかな実装(サニタイズする必要があります)

public class FileOperator {private static object locker = new object();

private static List<object> fileObjects;

private static Dictionary fileObjectsDictionary;     

public void DownloadAndDeleteFile(string fileName) 
{ 
    lock(locker) 
    { 
        if(fileObjects == null)
           fileObjects = new List<object>();

        if(fileObjectsDictionary == null)
           fileObjectsDictionary = new Dictionary();

        // check whether list contains fileName
        // For First time Add file to a given index
        // Create an Object using same index and add to the dictionary
        // For any other time get the index and fetch the object from dictionary
    } 

   lock(Dictionary Object)
    {
      // All business logic
    }
} 

}

//このように、すべてのスレッドが同じポイントで待機することはありません

お役に立てれば、

Mrinal

于 2012-07-27T06:41:12.223 に答える
1

Webサービスが単一のエントリポイントである場合、実際にはこれについてまったく心配する必要はありません。なんで?Webサービスを非同期で呼び出すことができる場合でも、Webサービスはデフォルトで同期方式で要求を実行します。ASMXWebService 、WCF、またはaspxページはデフォルトで非同期ですか。

于 2012-07-23T11:40:00.210 に答える
0

アトミックに削除してみませんか?

lock(obj)
    if(IO.File.Exists(someFilePath))
       try
       {
           IO.File.Delete(someFilePath));
        }catch(IOException){//do nothing}
于 2012-07-23T10:20:06.297 に答える