通过多个进程下载和读取相同的文件w/ c# 4.0

本文关键字:文件 进程 读取 下载和 | 更新日期: 2023-09-27 18:11:13

我需要能够读取应该保存在本地的文件,如果文件不存在,我需要下载它。以下是我想要完成的任务的简化版本:

// See if the file exists locally
if (!File.Exists(physicalPath))
{
    // file doesn't exist, download it
    using (WebClient client = new WebClient())
    {
        client.DownloadFile(url, physicalPath);
    }
}
// open up the file and do stuff ..

由于稍后发生的事情,我不能使用流,但我需要先将文件保存到磁盘。

对于一个调用来说一切都很好,但是正如您可以想象的那样,当1,000个进程同时运行该函数时将会出现问题。以下是我认为两个进程同时启动时会发生的情况:

流程1:

  1. 文件在本地存在吗?没有
  2. 开始下载
  3. 文件下载完成
  4. 读取文件

流程2:

  1. 文件在本地存在吗?是的
  2. 读取文件
  3. 异常! !文件正在被其他进程使用

所以进程2会看到文件存在,但这只是因为进程1已经在积极地下载文件,而进程1还没有下载完文件。我希望进程2(以及所有正在进行的其他进程)等待进程1完成文件下载。

在这里帮助我们的是,进程1下载的任何内容都可以用于进程2,这意味着进程2不会有不同的数据,也不需要写入文件。如果进程1正在下载文件,最好是进程2不必下载文件,它可以等待进程1完成。

那么总结一下,如果进程1已经在下载其他进程需要的文件,我该如何阻止其他进程继续,让它们等待进程1完成?一旦文件准备好,我如何使进程2继续?(使用c# 4.0)

我还应该澄清一下,这个操作的速度是优先级#1。

通过多个进程下载和读取相同的文件w/ c# 4.0

整个设置听起来有点容易出现竞争条件,很难调节。

我将创建一个单独的(单例)进程,负责将请求排队并下载给其他进程。您可以通过某种IPC(如WCF)与它对话。

使用互斥锁来同步进程。像这样的代码应该可以达到这个效果:

public static class FileRepository
{
    public static FileInfo GetFile(string fileName)
    {
        FileInfo MyFile;
        if(!File.Exists(fileName))
        {
            // Use some unique name + filename as Mutex Name
            using(new Mutex(true, fileName))
            {
                // Will block if another Process already downloads the file
                if(Mutex.WaitOne())
                {
                    // Download the File and safe FileInfo in MyFile
                    // ...
                }
            }
        }
        else
        {
            MyFile = new FileInfo(fileName);
        }       
        return MyFile;
    }
}