3

在 Windows 窗体窗口中,多个事件可以触发异步方法。此方法下载文件并缓存它。我的问题是我希望该方法执行一次。换句话说,我想防止文件被多次下载。

如果下载文件的方法被触发两次,我希望第二次调用等待文件(或等待第一个方法完成)。

有人知道如何实现这一目标吗?

更新:我只是想防止不必要的下载。在我的例子中,当客户端将鼠标悬停在 ListBox 中的某个项目上超过几毫秒时,我们开始下载。我们假设用户会点击并请求文件。可能发生的情况是用户将鼠标悬停在项目上一秒钟,然后单击。在这种情况下,两个下载开始。我正在寻找处理这种情况的最佳方法。

更新2::用户有可能将鼠标移到多个项目上。结果,将发生多次下载。我对这种情况并不是很严格,但现在如果我们遇到这种情况,我们不会放弃下载。该文件将被下载(文件通常在 50-100kb 左右),然后将被缓存。

4

6 回答 6

6

维护表单变量中正在发生的事情的状态,并让您的异步方法在执行任何操作之前检查该状态。不过,请确保您同步访问它!互斥量和信号量对这类事情很有用。

如果您可以同时下载不同的文件,则需要在列表中跟踪下载的内容以供参考。

如果一次只能下载一个文件,并且您不想排队,您也可以在下载内容时取消挂钩事件,并在下载完成后重新挂钩。

于 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

您可以简单地将您的方法调用包装在这样的锁定语句中

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 回答
0

一般来说,我同意Michaellock的观点,在实际获取文件的代码周围使用 a 。但是,如果有一个事件总是首先发生并且您始终可以加载文件,那么请考虑使用Futures。在初始事件中,开始未来的运行

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

在所有其他事件中,等待未来的价值

DoSomethingWith(file.Value);
于 2009-01-14T22:02:43.083 回答
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 回答