NServicebus与文件系统观察器

我希望我的端点在检测到特定文件夹中的文件被删除时发送一个事件。 我能够通过使用实现IWantToRunWhenBusStartsAndStops的类来实现它,后者又设置了一个FileSystemWatcher来监视给定的文件夹。 我的问题是,这是使用nservicebus进行此操作的最佳方式,还是我错过了可能导致我遇到麻烦的问题?

这是我的代码:

public class FileSystem : IWantToRunWhenBusStartsAndStops { private FileSystemWatcher watcher; public void Start() { ConfigFileWatcher(); } public void Stop() { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] private void ConfigFileWatcher() { watcher = new FileSystemWatcher(); watcher.Path = @"c:\"; /* Watch for changes in LastAccess and LastWrite times, and the renaming of files or directories. */ watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; // Only watch text files. watcher.Filter = "*.txt"; // Add event handlers. watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Created += new FileSystemEventHandler(OnChanged); watcher.Deleted += new FileSystemEventHandler(OnChanged); // Begin watching. watcher.EnableRaisingEvents = true; } // Define the event handlers. private static void OnChanged(object source, FileSystemEventArgs e) { // Specify what is done when a file is changed, created, or deleted. Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType); // fire off an event here... } 

}

如果您查看NServiceBus源代码,在容器初始化中,您将看到IWantToRunWhenBusStartsAndStops已注册,每个调用的生命周期为一个

 ForAllTypes(TypesToScan, t => configurer.ConfigureComponent(t, DependencyLifecycle.InstancePerCall)); 

这意味着在调用Start()之后将调度该类。 您的实现有效,因为您的事件订阅了静态处理程序,这使订阅保持活动状态。

我们在生产中使用文件观察者,但我们将它们作为高级卫星烘焙。 保证卫星被初始化为单体,不会被丢弃。 他们也有Start和Stop方法。 它们确实有地址并且应该能够处理传入的消息,但是您可以使用一些虚拟地址而不在处理程序中执行任何操作,除非您希望使文件系统观察器卫星双向(即接收消息并将它们作为文件放在磁盘上)。

在NServiceBus中, 建议将持续运行的非一次性过程作为卫星。 许多NServiceBus组件都是作为卫星制作的。

您可能会对如何自己制作卫星感到好奇,但这很容易做到。 您可以在此处查看界面签名。

它看起来像这样

 using System; using System.IO; using NServiceBus; using NServiceBus.Satellites; public class FileSystem : ISatellite { private FileSystemWatcher _watcher; public bool Handle(TransportMessage message) { return true; } public void Start() { _watcher = new FileSystemWatcher { Path = @"c:\", NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName, Filter = "*.txt" }; _watcher.Changed += OnChanged; _watcher.Created += OnChanged; _watcher.Deleted += OnChanged; _watcher.EnableRaisingEvents = true; } public void Stop() { _watcher.Dispose(); } public Address InputAddress { get { return Address.Parse("FileSystemSatellite"); } } public bool Disabled { get { return false; } } // Define the event handlers. private void OnChanged(object source, FileSystemEventArgs e) { // Specify what is done when a file is changed, created, or deleted. Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType); // fire off an event here... } } 

您需要记住一件事:每颗卫星都有自己的队列。 在这种情况下,它将始终为空。

基于其他答案和评论,我相信您的FileSystemWatcher通过订阅OnChanged事件而保持活力。

这实际上是内存泄漏的(相当)常见原因,但在您的情况下,它实际上会将您的观察者保留在内存中并允许其继续运行。 从OnChanged()方法中删除static关键字,我相信您会看到您期望的行为。

当然,您希望 FileSystemWatcher继续运行。 。 。 一个选项可能就是让观察者变量本身变为静态。 如果你走这条路,我会把它放在一个单独的类中,只需通过实现IWantToRunWhenBusStartsAndStops的类初始化它。