Как назначить отдельный поток для каждого наблюдателя файловой системы? - PullRequest
3 голосов
/ 23 февраля 2010

Я занимаюсь разработкой файловой системы базы данных . Она включает в себя средство просмотра нескольких каталогов, которое является службой Windows и использует класс наблюдателя файловой системы из .net.

Я хочу запустить каждый класс-наблюдатель в отдельном потоке. Невозможно расширить поток в .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)
    }
} }

Я застрял в этой точке. Пожалуйста, помогите мне.

Ответы [ 2 ]

12 голосов
/ 23 февраля 2010

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

UPDATE: Поскольку вы используете подход событий в FileSystemWatcher, вы уже используете многопоточный подход, потому что обработчики событий для каждого экземпляра FileSystemWatcher будут запускаться в отдельном потоке асинхронно.

0 голосов
/ 23 февраля 2010

Я бы написал новый класс, который обернет или адаптирует FileSystemWatcher, а затем запустит мой новый класс в новом потоке. Класс адаптера будет обрабатывать уведомления из класса FSW, и тогда вы сможете найти лучший способ широковещательной передачи или передачи этих уведомлений какой-то функции сортировки.

Есть несколько разных способов запуска новых потоков и миллиарды учебных пособий о том, как это сделать, поэтому я не буду описывать это здесь в этом ответе.

...