我正在尝试在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中的事件,但我无法找到解决方案。 非常感谢 发布
答案 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
方法中通过调用
var dest = paths[((FileSystemWatcher)sender).Path].destinations
答案 2 :(得分:0)
我有一个类似的程序作为Windows服务运行。我创建了一个XML配置文件,其中包含要监视的所有文件夹以及与每个路径对应的目标路径。然后,我为每个要观看的文件夹设置了另一个观察者线程。
为了拥有正确的输出路径,您需要将其与正在观看的文件夹配对。 因此,您可以使用配置文件,或类似Dictionary或KeyValuePairs列表。