NServicebus与文件系统观察器

时间:2015-03-20 15:35:57

标签: c# nservicebus filesystemwatcher

每当检测到特定文件夹中的文件被删除时,我希望我的端点发送一个事件。我能够通过使用实现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...
    }

}

2 个答案:

答案 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...
    }
}

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