每当检测到特定文件夹中的文件被删除时,我希望我的端点发送一个事件。我能够通过使用实现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...
}
}
答案 0 :(得分:3)
基于其他答案和评论,我相信您的FileSystemWatcher通过订阅OnChanged事件而保持活力。
这实际上是内存泄漏的(相当)常见原因,但在您的情况下,它实际上会将您的观察者保留在内存中并允许其继续运行。从OnChanged()方法中删除static关键字,我相信你会看到你期望的行为。
当然,您希望 FileSystemWatcher继续运行。 。 。一个选项可能就是让观察者变量本身变为静态。如果你走这条路,我会把它放在一个单独的类中,只需通过实现IWantToRunWhenBusStartsAndStops的类初始化它。
答案 1 :(得分:1)
如果查看NServiceBus源代码,在容器初始化中,您将看到IWantToRunWhenBusStartsAndStops已注册,每次调用的生命周期为
ForAllTypes<IWantToRunWhenBusStartsAndStops>(TypesToScan, t => configurer.ConfigureComponent(t, DependencyLifecycle.InstancePerCall));
这意味着在调用Start()之后将调度该类。您的实现是有效的,因为您的事件订阅了静态处理程序,这使订阅保持活动状态。
我们在生产中使用文件观察者,但我们将它们作为高级卫星烘焙。保证卫星被初始化为单身,不会被丢弃。他们也有Start和Stop方法。它们确实有地址并且应该能够处理传入的消息,但是您可以使用一些虚拟地址并且在处理程序中不执行任何操作,除非您希望使文件系统观察器卫星双向(即接收消息并将它们作为文件放在磁盘上)。
在NServiceBus中,推荐可以使持续运行的非一次性流程成为卫星。许多NServiceBus组件都是作为卫星制作的。
您可能会对如何自己制作卫星感到好奇,但这很容易做到。您可以检查界面签名here。
它看起来像这样
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...
}
}
您需要记住一件事:每颗卫星都有自己的队列。在这种情况下,它将始终为空。