我正在开发一个database file system。它包含一个多目录观察程序,它是一个Windows服务,它使用来自.net的file system watcher类。
我想在单独的线程上运行每个观察者类。线程无法在.net中扩展,因为它是“密封”的。 我想要的是,在相关的线程中运行我的观察者类的所有方法。 我怎样才能做到这一点?
编辑 -
以下是我的基础守望者课程。
public abstract class WatcherBase
{
private IWatchObject _watchObject;
public WatcherBase() { }
public WatcherBase(IWatchObject watchObject, bool canPauseAndContinue)
{
_watchObject = watchObject;
CanPauseAndContinue = canPauseAndContinue;
}
public bool CanPauseAndContinue { get; set; }
public IWatchObject ObjectToWatch
{
get
{
return _watchObject;
}
}
public abstract void Start();
public abstract void Pause();
public abstract void Continue();
public abstract void Stop();
}
以下是我从WatcherBase类扩展的目录监视器类
namespace RankFs.WatcherService
{
public class DirectoryWatcher : WatcherBase
{
private WatchDirectory _directoryToWatch;
private FileSystemWatcher _watcher;
public DirectoryWatcher(WatchDirectory directory, bool CanPauseAndContinue)
:base(directory ,CanPauseAndContinue)
{
_directoryToWatch = directory;
_watcher = new FileSystemWatcher(_directoryToWatch.Path);
_watcher.IncludeSubdirectories = _directoryToWatch.WatchSubDirectories;
_watcher.Created +=new FileSystemEventHandler(Watcher_Created);
//_watcher.Changed +=new FileSystemEventHandler(Watcher_Changed);
_watcher.Deleted +=new FileSystemEventHandler(Watcher_Deleted);
_watcher.Renamed +=new RenamedEventHandler(Watcher_Renamed);
}
public WatchDirectory DirectoryToWatch
{
get
{
return _directoryToWatch;
}
}
public override void Start()
{
_watcher.EnableRaisingEvents = true;
}
public override void Pause()
{
_watcher.EnableRaisingEvents = false;
}
public override void Continue()
{
_watcher.EnableRaisingEvents = true;
}
public override void Stop()
{
_watcher.EnableRaisingEvents = false;
}
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
// adds a new file entry to database
}
private void Watcher_Deleted(object sender, FileSystemEventArgs e)
{
//updates the database(deleted file)
}
private void Watcher_Renamed(object sender, RenamedEventArgs e)
{
//updates the database(renamed file)
}
} }
我现在陷入困境。请帮助我。
答案 0 :(得分:12)
FileSystemWatcher
将在单独的线程中触发事件。事件处理程序内部的逻辑需要考虑这一事实并执行所需的任何同步。
如果运行以下示例,您将看到Changed
事件处理程序将在另一个线程中运行。
public static void Main(string[] args)
{
Directory.CreateDirectory("dir1");
Directory.CreateDirectory("dir2");
Directory.CreateDirectory("dir3");
Console.WriteLine("Main Thread Id: {0}",
Thread.CurrentThread.ManagedThreadId);
const int watcherCount = 3;
string[] dirs = new string[] { "dir1", "dir2", "dir3" };
for (int i = 0; i < watcherCount; i++)
{
var watcher = new FileSystemWatcher();
watcher.Path = dirs[i];
watcher.Changed += (sender, e) =>
{
Console.WriteLine("File: {0} | Thread: {1}", e.Name,
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000); // Simulate long operation
};
watcher.EnableRaisingEvents = true;
}
File.WriteAllText(@"dir1\test1", "hello");
File.WriteAllText(@"dir2\test2", "hello");
File.WriteAllText(@"dir3\test3", "hello");
Thread.Sleep(10000);
}
运行此示例时,我获得了以下输出:
// Main Thread Id: 1
// File: test1 | Thread: 3
// File: test2 | Thread: 4
// File: test3 | Thread: 5
// File: test1 | Thread: 3
// File: test2 | Thread: 4
// File: test3 | Thread: 5
<强>更新强>
由于您在FileSystemWatcher
中使用事件方法,因此您已经在使用多线程方法,因为每个FileSystemWatcher
实例的事件处理程序将以异步方式在单独的线程中触发。
答案 1 :(得分:0)
我会编写一个wraps or adapts FileSystemWatcher的新类,然后在新线程上启动我的新类。适配器类将处理来自FSW类的通知,然后您可以找出将这些通知广播或中继到某种编组功能的最佳方法。
有几种不同的方式来发布新线程和数十亿关于如何做的教程,所以我不打算在这里回答这个问题。