C#:FileSystemWatcher - 多个观看文件夹问题

时间:2014-07-10 09:23:18

标签: c# filesystemwatcher

我正在尝试在c#中编写正在观看多个文件夹的程序。如果在任何监视文件夹中添加了文件,程序应在定义的路径中创建副本。 我的问题是当我创建文件时,程序在错误的文件夹中创建副本

e.g。如果我将文件添加到

 C:\folder1\stuff\ 
,它应该在
 D:\stuff1\copied1...3\
中创建副本 但它改为在
 D:\stuff2\copied1...3\

中创建副本

有代码:

namespace Watcher
{
    public class Watcher
    {

        struct Paths
        {
            public string sourcePath;
            public List<string> destinations;
            public FileSystemWatcher Watcher;
        }

        List<Paths> paths = new List<Paths>();

        public Watcher()
        {
            createWatchTower();
        }

        public void watch()
        {
            foreach (Paths p in paths)
            {
                p.Watcher.Created += (sender, e) => onCreate(sender, e, p.destinations);
            }
        }

        void createWatchTower()
        {
            Paths p1;
            p1.destinations = new List<string>();

            p1.sourcePath = @"C:\folder1\stuff\";

            p1.Watcher = new FileSystemWatcher();
            p1.Watcher.Path = p1.sourcePath;
            p1.Watcher.EnableRaisingEvents = true;

            p1.destinations.Add(@"D:\stuff1\copied1\");
            p1.destinations.Add(@"D:\stuff1\copied2\");
            p1.destinations.Add(@"D:\stuff1\copied3\");
            paths.Add(p1);


            Paths p2;
            p2.destinations = new List<string>();
            p2.sourcePath = @"C:\folder2\stuff2";

            p2.Watcher = new FileSystemWatcher();
            p2.Watcher.Path = p2.sourcePath;
            p2.Watcher.EnableRaisingEvents = true;

            p2.destinations.Add(@"D:\stuff2\copied1\");
            p2.destinations.Add(@"D:\stuff2\copied2\");
            p2.destinations.Add(@"D:\stuff2\copied3\");

            paths.Add(p2);

        }

        private void onCreate(object o, FileSystemEventArgs e, List<string> dest)
        {

            foreach (string s in dest)
            {
                try
                {
                    System.IO.File.Copy(e.FullPath, s + e.Name, true);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }
    }
}

有人能帮帮我吗?我认为这是因为foreach中的事件,但我无法找到解决方案。 非常感谢 发布

3 个答案:

答案 0 :(得分:5)

如果您没有使用C#5,则问题是p方法中foreach循环中watch的关闭:

foreach (Paths p in paths)
{
    p.Watcher.Created += (sender, e) => onCreate(sender, e, p.destinations);
}

在lambda中使用p时,它将捕获变量,而不是其值。因此,如果Created事件被引发p,则会引用paths列表的最后一项。

你可以通过在foreach循环中引入一个临时变量来避免这种情况:

foreach (Paths p in paths)
{
    var tmp = p;
    p.Watcher.Created += (sender, e) => onCreate(sender, e, tmp.destinations);
}

您可以在this Stackoverflow question中找到有关C#5更改内容的更详细分析。

答案 1 :(得分:0)

您可以将路径创建为Dictionary(sourcePath =&gt; p)而不是List,并在onCreate方法中通过调用

获取destionation
var dest = paths[((FileSystemWatcher)sender).Path].destinations

答案 2 :(得分:0)

我有一个类似的程序作为Windows服务运行。我创建了一个XML配置文件,其中包含要监视的所有文件夹以及与每个路径对应的目标路径。然后,我为每个要观看的文件夹设置了另一个观察者线程。

为了拥有正确的输出路径,您需要将其与正在观看的文件夹配对。 因此,您可以使用配置文件,或类似Dictionary或KeyValuePairs列表。