public ContactWatcher(Dispatcher dispatcher, ContactLoader loader, string directory, ContactWatcherEventCallback callback) { // Assert here rather than dynamically generate these arrays. This class should include all the supported types. Assert.AreEqual(Contact.GetExtensionsFromType(ContactTypes.All).Split('|').Length, _Types.Length); var watchers = new ContactWatcherSingular[_Types.Length]; try { for (int i = 0; i < _Types.Length; ++i) { watchers[i] = new ContactWatcherSingular(dispatcher, loader, directory, _Types[i], callback); } _watchers = watchers; watchers = null; } finally { if (null != watchers) { foreach (ContactWatcherSingular watcher in watchers) { if (null != watcher) { watcher.Dispose(); } } } } }
public ContactWatcherSingular(Dispatcher dispatcher, ContactLoader loader, string directory, ContactTypes type, ContactWatcherEventCallback callback) { Assert.IsNotNull(dispatcher); // It's expected that this is created on the same thread as the manager, // so don't need to go through the dispatcher for methods invoked in the constructor. Assert.IsTrue(dispatcher.CheckAccess()); Assert.IsNotNull(loader); Assert.IsFalse(string.IsNullOrEmpty(directory)); Assert.IsNotNull(callback); Assert.IsTrue(Enum.IsDefined(typeof(ContactTypes), type)); Assert.AreNotEqual(ContactTypes.All, type); Assert.AreNotEqual(ContactTypes.None, type); _dispatcher = dispatcher; _rootDirectory = directory; _loader = loader; _notify = callback; _findExtension = "*" + Contact.GetExtensionsFromType(type); // This is why creating this object is expensive: // In order to be able to give accurate change notifications we need to know all the contacts that are present at the beginning. _knownContacts = new Dictionary<string, ContactInfo>(); // _pushedFrames = 0; _frame = new DispatcherFrame { Continue = false }; // Create the timer, but only signal it if we're going to need to reprocess an update. _timer = new Timer(); _timer.Tick += delegate { if (!_stopProcessing) { // Not invoked by the FileSystemWatcher, so don't push a frame here. _dispatcher.Invoke(DispatcherPriority.Background, (ThreadStart)_ReprocessPendingUpdate); } }; _timer.Interval = TimeSpan.FromMilliseconds(_TimerMsDelay); _timer.IsEnabled = false; _PopulateKnownContacts(type); _fileWatch = new FileSystemWatcher(_rootDirectory, _findExtension) { IncludeSubdirectories = true, NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Attributes, }; // There's some extra indirection required here because the manager requires thread affinity. _fileWatch.Changed += FileSystemWatcher_OnChanged; _fileWatch.Created += FileSystemWatcher_OnCreated; _fileWatch.Deleted += FileSystemWatcher_OnDeleted; _fileWatch.Renamed += FileSystemWatcher_OnRenamed; _fileWatch.EnableRaisingEvents = true; }