private bool ShouldThrottleEvent(EventThrottleKey key) { Timer timer; if (_eventQueue.TryGetValue(key, out timer)) { // do nothing. The same event was published a tick ago. return(true); } _eventQueue[key] = new Timer(RemoveFromEventQueue, key, 500, Timeout.Infinite); return(false); }
private void OnThemeFileChanged(string name, string fullPath, ThemeFileChangeType changeType) { // Enable event throttling by allowing the very same event to be published only all 500 ms. var throttleKey = new EventThrottleKey(name, changeType); if (ShouldThrottleEvent(throttleKey)) { return; } if (!_fileFilterPattern.IsMatch(Path.GetExtension(name))) { return; } var idx = name.IndexOf('\\'); if (idx < 0) { // must be a subfolder of "~/Themes/" return; } var themeName = name.Substring(0, idx); var relativePath = name.Substring(themeName.Length + 1).Replace('\\', '/'); var isConfigFile = relativePath.IsCaseInsensitiveEqual("theme.config"); if (changeType == ThemeFileChangeType.Modified && !isConfigFile) { // Monitor changes only for root theme.config return; } BaseThemeChangedEventArgs baseThemeChangedArgs = null; if (isConfigFile) { // config file changes always result in refreshing the corresponding theme manifest var di = new DirectoryInfo(Path.GetDirectoryName(fullPath)); string oldBaseThemeName = null; var oldManifest = this.GetThemeManifest(di.Name); if (oldManifest != null) { oldBaseThemeName = oldManifest.BaseThemeName; } try { // FS watcher in conjunction with some text editors fires change events twice and locks the file. // Let's wait max. 250 ms till the lock is gone (hopefully). WaitForUnlock(fullPath); var newManifest = ThemeManifest.Create(di.FullName, _themesBasePath); if (newManifest != null) { this.AddThemeManifestInternal(newManifest, false); if (!oldBaseThemeName.IsCaseInsensitiveEqual(newManifest.BaseThemeName)) { baseThemeChangedArgs = new BaseThemeChangedEventArgs { ThemeName = newManifest.ThemeName, BaseTheme = newManifest.BaseTheme != null ? newManifest.BaseTheme.ThemeName : null, OldBaseTheme = oldBaseThemeName }; } Logger.Debug("Changed theme manifest for '{0}'".FormatCurrent(name)); } else { // something went wrong (most probably no 'theme.config'): remove the manifest TryRemoveManifest(di.Name); } } catch (Exception ex) { Logger.Error(ex, "Could not touch theme manifest '{0}': {1}".FormatCurrent(name, ex.Message)); TryRemoveManifest(di.Name); } } if (baseThemeChangedArgs != null) { RaiseBaseThemeChanged(baseThemeChangedArgs); } RaiseThemeFileChanged(new ThemeFileChangedEventArgs { ChangeType = changeType, FullPath = fullPath, ThemeName = themeName, RelativePath = relativePath, IsConfigurationFile = isConfigFile }); }