5

我有以下场景,我必须复制多个(大约 10,50,200,...)文件。我一个接一个地同步进行。这是我的代码片段。

static void Main(string[] args)
        {
            string path = @"";
            FileSystemWatcher listener = new FileSystemWatcher(path);
            listener.Created += new FileSystemEventHandler(listener_Created);
            listener.EnableRaisingEvents = true;

            while (Console.ReadLine() != "exit") ;
        }

        public static void listener_Created(object sender, FileSystemEventArgs e)
        {
            while (!IsFileReady(e.FullPath)) ;
            File.Copy(e.FullPath, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" + e.Name);
        }

因此,当在某个文件夹中创建文件并准备好使用时,我会一个接一个地复制该文件,但是一旦任何文件准备好使用,我就需要开始复制。所以我认为我应该使用线程。那么..如何实现并行复制?

@克里斯

检查文件是否准备好

public static bool IsFileReady(String sFilename)
        {
            // If the file can be opened for exclusive access it means that the file
            // is no longer locked by another process.
            try
            {
                using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    if (inputStream.Length > 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }

                }
            }
            catch (Exception)
            {
                return false;
            }
        }
4

3 回答 3

12

从机械磁盘执行并行 I/O 是一个坏主意,只会减慢速度,因为机械头每次都需要旋转以寻找下一个读取位置(一个非常慢的过程),然后会随着每个线程反弹轮到它运行了。

坚持顺序方法并在单个线程中读取文件。

于 2012-06-14T08:09:06.550 回答
2

您可能有一个Thread可以完成所有处理的设备,即

Queue files = new Queue();

static void Main(string[] args)
{
      string path = @"";
      FileSystemWatcher listener = new FileSystemWatcher(path);
      Thread t = new Thread(new ThreadStart(ProcessFiles));
      t.Start();
      listener.Created += new FileSystemEventHandler(listener_Created);
      listener.EnableRaisingEvents = true;

      while (Console.ReadLine() != "exit") ;
}


public static void listener_Created(object sender, FileSystemEventArgs e)
{
    files.Enqueue(e.FullPath);
}

void ProcessFiles()
{
    while(true)
    {
        if(files.Count > 0)
        {
              String file = files.Dequeue();
              while (!IsFileReady(file)) ;

              File.Copy(file, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" +           file);
        }
    }
}

并在您的listener事件中将文件名添加到队列中。

然后,您Thread可以从队列中获取文件名并从那里进行处理。

于 2012-06-14T08:59:41.143 回答
2

现在仅此而已(@Tudor 所说的),但是由于碎片,并行复制文件会在您的硬盘驱动器中造成混乱。在我的应用程序中,我使用队列复制 200 个先前同时生成的文件,只是为了将它们以“线性”方式放在硬盘上。

您可以在此处阅读有关该主题的更多信息。

于 2012-06-14T08:19:36.310 回答