Index: XmlConfigurator.cs =================================================================== --- XmlConfigurator.cs (revision 607768) +++ XmlConfigurator.cs (working copy) @@ -870,9 +870,23 @@ try { - // Create a watch handler that will reload the - // configuration whenever the config file is modified. - ConfigureAndWatchHandler.StartWatching(repository, configFile); + lock (m_repositoryName2ConfigAndWatchHandler) + { + // support multiple repositories each having their own watcher + ConfigureAndWatchHandler handler = + (ConfigureAndWatchHandler)m_repositoryName2ConfigAndWatchHandler[repository.Name]; + + if (handler != null) + { + m_repositoryName2ConfigAndWatchHandler.Remove(repository.Name); + handler.Dispose(); + } + + // Create and start a watch handler that will reload the + // configuration whenever the config file is modified. + handler = new ConfigureAndWatchHandler(repository, configFile); + m_repositoryName2ConfigAndWatchHandler[repository.Name] = handler; + } } catch(Exception ex) { @@ -903,24 +917,9 @@ /// elapse. /// /// - private sealed class ConfigureAndWatchHandler + private sealed class ConfigureAndWatchHandler : IDisposable { /// - /// Watch a specified config file used to configure a repository - /// - /// The repository to configure. - /// The configuration file to watch. - /// - /// - /// Watch a specified config file used to configure a repository - /// - /// - internal static void StartWatching(ILoggerRepository repository, FileInfo configFile) - { - new ConfigureAndWatchHandler(repository, configFile); - } - - /// /// Holds the FileInfo used to configure the XmlConfigurator /// private FileInfo m_configFile; @@ -941,8 +940,15 @@ /// private const int TimeoutMillis = 500; + /// + /// Watches file for changes. This object should be disposed when no longer + /// needed to free system handles on the watched resources. + /// + private FileSystemWatcher m_watcher; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class to + /// watch a specified config file used to configure a repository. /// /// The repository to configure. /// The configuration file to watch. @@ -951,31 +957,31 @@ /// Initializes a new instance of the class. /// /// - private ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile) + public ConfigureAndWatchHandler(ILoggerRepository repository, FileInfo configFile) { m_repository = repository; m_configFile = configFile; // Create a new FileSystemWatcher and set its properties. - FileSystemWatcher watcher = new FileSystemWatcher(); + m_watcher = new FileSystemWatcher(); - watcher.Path = m_configFile.DirectoryName; - watcher.Filter = m_configFile.Name; + m_watcher.Path = m_configFile.DirectoryName; + m_watcher.Filter = m_configFile.Name; // Set the notification filters - watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; + m_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; // Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs - watcher.Changed += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - watcher.Created += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - watcher.Deleted += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); - watcher.Renamed += new RenamedEventHandler(ConfigureAndWatchHandler_OnRenamed); + m_watcher.Changed += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Created += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Deleted += new FileSystemEventHandler(ConfigureAndWatchHandler_OnChanged); + m_watcher.Renamed += new RenamedEventHandler(ConfigureAndWatchHandler_OnRenamed); // Begin watching. - watcher.EnableRaisingEvents = true; + m_watcher.EnableRaisingEvents = true; // Create the timer that will be used to deliver events. Set as disabled - m_timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite); + m_timer = new Timer(new TimerCallback(OnWatchedFileChange), null, Timeout.Infinite, Timeout.Infinite); } /// @@ -1019,11 +1025,21 @@ /// /// Called by the timer when the configuration has been updated. /// - /// null + /// null private void OnWatchedFileChange(object state) { XmlConfigurator.InternalConfigure(m_repository, m_configFile); } + + /// + /// Release the handles held by the watcher and timer. + /// + public void Dispose() + { + m_watcher.EnableRaisingEvents = false; + m_watcher.Dispose(); + m_timer.Dispose(); + } } #endif @@ -1083,6 +1099,13 @@ #region Private Static Fields + /// + /// Maps repository names to ConfigAndWatchHandler instances to allow a particular + /// ConfigAndWatchHandler to dispose of its FileSystemWatcher when a repository is + /// reconfigured. + /// + private readonly static Hashtable m_repositoryName2ConfigAndWatchHandler = new Hashtable(); + /// /// The fully qualified type of the XmlConfigurator class. ///