3

Windows フォーム ウィンドウでは、複数のイベントが非同期メソッドをトリガーできます。このメソッドは、ファイルをダウンロードしてキャッシュします。私の問題は、そのメソッドを一度実行したいということです。つまり、ファイルが複数回ダウンロードされるのを防ぎたいのです。

ファイルをダウンロードするメソッドが 2 回トリガーされた場合、2 回目の呼び出しでファイルを待機する (または最初のメソッドが実行されるのを待機する) 必要があります。

誰かがそれを達成する方法について考えを持っていますか?

更新:不要なダウンロードを防止しようとしているだけです。私の場合、クライアントが数ミリ秒以上 ListBox 内のアイテムの上にマウスを置くと、ダウンロードが開始されます。ユーザーがクリックしてファイルを要求すると想定しています。ユーザーがアイテムの上にマウスを 1 秒間置いてからクリックすると、発生する可能性があります。この場合、2 つのダウンロードが開始されます。そのようなシナリオを処理するための最良の方法を探しています。

更新 2: : ユーザーがマウスを複数の項目の上に移動する可能性があります。その結果、複数のダウンロードが発生します。私はこのシナリオにそれほど苦労していませんが、現時点では、そのようなシナリオに直面した場合でも、ダウンロードを放棄することはありません. ファイルがダウンロードされ (通常、ファイルは約 50 ~ 100kb です)、キャッシュされます。

4

6 に答える 6

6

フォーム変数で起こっていることの状態を維持し、非同期メソッドが何かを行う前にその状態をチェックするようにします。ただし、アクセスを同期するようにしてください。ミューテックスとセマフォは、この種のものに適しています。

異なるファイルを同時にダウンロードできる場合は、ダウンロード中のファイルを参照用のリストで追跡する必要があります。

一度に 1 つのファイルしかダウンロードできず、キューに入れたくない場合は、ダウンロード中にイベントをフック解除し、ダウンロードが完了したら再度フックすることができます。

于 2009-01-14T21:25:30.177 に答える
2

複数のファイルのダウンロードをサポートするダミーの実装を次に示します。

    Dictionary<string, object> downloadLocks = new Dictionary<string, object>();

    void DownloadFile(string localFile, string url)
    {
        object fileLock; 
        lock (downloadLocks)
        {
            if (!downloadLocks.TryGetValue(url, out fileLock))
            {
                fileLock = new object(); 
                downloadLocks[url] = fileLock;
            }
        }

        lock (fileLock)
        {
            // check if file is already downloaded 

            // if not then download file
        }
    }
于 2009-01-14T21:50:36.010 に答える
0

あるスレッドが別のスレッドがタスクを終了するのを待つようにしたい場合は、おそらくManualResetEventを使用することをお勧めします。多分このようなもの:

private ManualResetEvent downloadCompleted = new ManualResetEvent();
private bool downloadStarted = false;

public void Download()
{
   bool doTheDownload = false;

   lock(downloadCompleted)
   {
       if (!downloadStarted)
       { 
            downloadCompleted.Reset();
            downloadStarted = true;
            doTheDownload = true;
       }
   }

   if (doTheDownload)
   {
       // Code to do the download

       lock(downloadCompleted)
       {
           downloadStarted = false;
       }
       // When finished notify anyone waiting.
       downloadCompleted.Set();
   }
   else
   {
       // Wait until it is done... 
       downloadCompleted.WaitOne();
   }

}
于 2009-01-14T22:12:46.977 に答える
0

一般に、 Michaelに同意しlockます。実際にファイルを取得するコードの周りにa を使用します。ただし、常に最初に発生する単一のイベントがあり、いつでもファイルをロードできる場合は、Futuresの使用を検討してください。最初のイベントで、将来の実行を開始します

Future<String> file = InThe.Future<String>(delegate { return LoadFile(); });

そして他のすべてのイベントでは、未来の値を待ちます

DoSomethingWith(file.Value);
于 2009-01-14T22:02:43.083 に答える
0

このように、lock ステートメント内でメソッド呼び出しをラップするだけです。

private static readonly Object padLock = new Object();

...
lock(padLock)
{
    YourMethod();
}
于 2009-01-14T21:24:30.990 に答える
0

C# でどのように実行されるかはわかりませんが、Java では、ファイルをダウンロードする前に、クラス内のプライベートな静的最終オブジェクトで同期します。これにより、現在のリクエストが完了するまで、それ以降のリクエストがブロックされます。その後、ファイルがダウンロードされたかどうかを確認し、適切に対処できます。

private static final Object lock = new Object();
private File theFile;

public method() {
  synchronized(lock) {
    if(theFile != null) {
      //download the file
    }
  }
}
于 2009-01-14T21:24:53.313 に答える