从另一个CS文件调用delegate()?

时间:2013-02-08 14:30:55

标签: c# wpf multithreading delegates filesystems

我正在尝试练习文件监视的示例。因此,基本思想是创建一个独立的线程来监视监视文件夹中的任何事件。原始程序是基于Windows窗体的,我试图将其转换为框架工作3.5,C#+ WPF;

响应事件的委托函数在A.cs中定义,它们看起来像:

public class WatcherEx : IDisposable
    {
        #region Data Members
        private bool           disposed    = false;
        private WatcherInfo    watcherInfo = null;
        private WatchersExList watchers    = new WatchersExList();
        #endregion Data Members

        #region Event Definitions
        public event WatcherExEventHandler EventChangedAttribute     = delegate {};
        public event WatcherExEventHandler EventChangedCreationTime  = delegate {};
        public event WatcherExEventHandler EventChangedDirectoryName = delegate {};
        public event WatcherExEventHandler EventChangedFileName      = delegate {};
        public event WatcherExEventHandler EventChangedLastAccess    = delegate {};
        public event WatcherExEventHandler EventChangedLastWrite     = delegate {};
        public event WatcherExEventHandler EventChangedSecurity      = delegate {};
        public event WatcherExEventHandler EventChangedSize          = delegate {};
        public event WatcherExEventHandler EventCreated              = delegate {};
        public event WatcherExEventHandler EventDeleted              = delegate {};
        public event WatcherExEventHandler EventRenamed              = delegate {};
        public event WatcherExEventHandler EventError                = delegate {};
        public event WatcherExEventHandler EventDisposed             = delegate {};
        public event WatcherExEventHandler EventPathAvailability     = delegate {};
        #endregion Event Definitions

        #region Constructors
        //--------------------------------------------------------------------------------
        public WatcherEx(WatcherInfo info)
        {
            if (info == null)
            {
                throw new Exception("WatcherInfo object cannot be null");
            }
            this.watcherInfo = info;

            Initialize();
        }
        #endregion Constructors

        #region Dispose Methods
        //--------------------------------------------------------------------------------
        /// <summary>
        /// Disposes all of the FileSystemWatcher objects, and disposes this object.
        /// </summary>
        public void Dispose()
        {
            Debug.WriteLine("WatcherEx.Dispose()");
            if (!this.disposed)
            {
                DisposeWatchers();
                this.disposed = true;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Disposes of all of our watchers (called from Dispose, or as a result of 
        /// loosing access to a folder)
        /// </summary>
        public void DisposeWatchers()
        {
            Debug.WriteLine("WatcherEx.DisposeWatchers()");
            for (int i = 0; i < this.watchers.Count; i++)
            {
                this.watchers[i].Dispose();
            }
            this.watchers.Clear();
        }
        #endregion Dispose Methods

        #region Helper Methods
        //--------------------------------------------------------------------------------
        /// <summary>
        /// Determines if the specified NotifyFilter item has been specified to be 
        /// handled by this object.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public bool HandleNotifyFilter(NotifyFilters filter)
        {
            return (((NotifyFilters)(this.watcherInfo.ChangesFilters & filter)) == filter);
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Determines if the specified WatcherChangeType item has been specified to be 
        /// handled by this object.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public bool HandleWatchesFilter(WatcherChangeTypes filter)
        {
            return (((WatcherChangeTypes)(this.watcherInfo.WatchesFilters & filter)) == filter);
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Initializes this oibject by creating all of the required internal 
        /// FileSystemWatcher objects necessary to mointor the folder/file for the 
        /// desired changes
        /// </summary>
        private void Initialize()
        {
            Debug.WriteLine("WatcherEx.Initialize()");
            // the buffer can be from 4 to 64 kbytes.  Default is 8
            this.watcherInfo.BufferKBytes = Math.Max(4, Math.Min(this.watcherInfo.BufferKBytes, 64));

            // create the main watcher (handles create/delete, rename, error, and dispose)
            // can't pass a null enum type, so we just pass ta dummy one on the first call
            CreateWatcher(false, this.watcherInfo.ChangesFilters);
            // create a change watcher for each NotifyFilter item
            CreateWatcher(true, NotifyFilters.Attributes);
            CreateWatcher(true, NotifyFilters.CreationTime);
            CreateWatcher(true, NotifyFilters.DirectoryName);
            CreateWatcher(true, NotifyFilters.FileName);
            CreateWatcher(true, NotifyFilters.LastAccess);
            CreateWatcher(true, NotifyFilters.LastWrite);
            CreateWatcher(true, NotifyFilters.Security);
            CreateWatcher(true, NotifyFilters.Size);

            Debug.WriteLine(string.Format("WatcherEx.Initialize() - {0} watchers created", this.watchers.Count));
        }


        //--------------------------------------------------------------------------------
        /// <summary>
        /// Actually creates the necessary FileSystemWatcher objects, depending oin which 
        /// notify filters and change types the user specified.
        /// </summary>
        /// <param name="changeType"></param>
        /// <param name="filter"></param>
        private void CreateWatcher(bool changedWatcher, NotifyFilters filter)
        {
            Debug.WriteLine(string.Format("WatcherEx.CreateWatcher({0}, {1})", changedWatcher.ToString(), filter.ToString()));

            FileSystemWatcherEx watcher = null;
            int bufferSize = (int)this.watcherInfo.BufferKBytes * 1024;
            // Each "Change" filter gets its own watcher so we can determine *what* 
            // actually changed. This will allow us to react only to the change events 
            // that we actually want.  The reason I do this is because some programs 
            // fire TWO events for  certain changes. For example, Notepad sends two 
            // events when a file is created. One for CreationTime, and one for 
            // Attributes.
            if (changedWatcher)
            {
                // if we're not handling the currently specified filter, get out
                if (HandleNotifyFilter(filter))
                {
                    watcher                       = new FileSystemWatcherEx(this.watcherInfo.WatchPath);
                    watcher.IncludeSubdirectories = this.watcherInfo.IncludeSubFolders;
                    watcher.Filter                = this.watcherInfo.FileFilter;
                    watcher.NotifyFilter          = filter;
                    watcher.InternalBufferSize    = bufferSize;
                    switch (filter)
                    {
                        case NotifyFilters.Attributes    :
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedAttribute);
                            break;
                        case NotifyFilters.CreationTime  : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedCreationTime);
                            break;
                        case NotifyFilters.DirectoryName : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedDirectoryName);
                            break;
                        case NotifyFilters.FileName      : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedFileName);
                            break;
                        case NotifyFilters.LastAccess    : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedLastAccess);
                            break;
                        case NotifyFilters.LastWrite     : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedLastWrite);
                            break;
                        case NotifyFilters.Security      : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedSecurity);
                            break;
                        case NotifyFilters.Size          : 
                            watcher.Changed += new FileSystemEventHandler(watcher_ChangedSize);
                            break;
                    }
                }
            }
            // All other FileSystemWatcher events are handled through a single "main" 
            // watcher.
            else
            {
                if (HandleWatchesFilter(WatcherChangeTypes.Created) ||
                    HandleWatchesFilter(WatcherChangeTypes.Deleted) ||
                    HandleWatchesFilter(WatcherChangeTypes.Renamed) ||
                    this.watcherInfo.WatchForError ||
                    this.watcherInfo.WatchForDisposed)
                {
                    watcher                       = new FileSystemWatcherEx(this.watcherInfo.WatchPath, watcherInfo.MonitorPathInterval);
                    watcher.IncludeSubdirectories = this.watcherInfo.IncludeSubFolders;
                    watcher.Filter                = this.watcherInfo.FileFilter;
                    watcher.InternalBufferSize    = bufferSize;
                }

                if (HandleWatchesFilter(WatcherChangeTypes.Created)) 
                {
                    watcher.Created += new FileSystemEventHandler(watcher_CreatedDeleted);
                }
                if (HandleWatchesFilter(WatcherChangeTypes.Deleted))
                {
                    watcher.Deleted += new FileSystemEventHandler(watcher_CreatedDeleted);
                }
                if (HandleWatchesFilter(WatcherChangeTypes.Renamed))
                {
                    watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
                }
                if (watcherInfo.MonitorPathInterval > 0)
                {
                    watcher.EventPathAvailability += new PathAvailabilityHandler(watcher_EventPathAvailability);
                }
            }
            if (watcher != null)
            {
                if (this.watcherInfo.WatchForError)
                {
                    watcher.Error += new ErrorEventHandler(watcher_Error);
                }
                if (this.watcherInfo.WatchForDisposed)
                {
                    watcher.Disposed += new EventHandler(watcher_Disposed);
                }
                this.watchers.Add(watcher);
            }
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Starts all of the internal FileSystemWatcher objects by setting their 
        /// EnableRaisingEvents property to true.
        /// </summary>
        public void Start()
        {
            Debug.WriteLine("WatcherEx.Start()");
            this.watchers[0].StartFolderMonitor();
            for (int i = 0; i < this.watchers.Count; i++)
            {
                this.watchers[i].EnableRaisingEvents = true;
            }
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Stops all of the internal FileSystemWatcher objects by setting their 
        /// EnableRaisingEvents property to true.
        /// </summary>
        public void Stop()
        {
            Debug.WriteLine("WatcherEx.Stop()");
            this.watchers[0].StopFolderMonitor();
            for (int i = 0; i < this.watchers.Count; i++)
            {
                this.watchers[i].EnableRaisingEvents = false;
            }
        }
        #endregion Helper Methods

        #region Native Watcher Events
        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring attribute changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedAttribute(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed Attribute");
            EventChangedAttribute(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.Attributes));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring creation time changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedCreationTime(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed CreationTime");
            EventChangedCreationTime(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.CreationTime));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring directory name changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedDirectoryName(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed DirectoryName");
            EventChangedDirectoryName(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.DirectoryName));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring file name changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedFileName(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed FileName");
            EventChangedFileName(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.FileName));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring last access date/time 
        /// changes is triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedLastAccess(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed LastAccess");
            EventChangedLastAccess(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.LastAccess));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring last write date/time 
        /// changes is triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedLastWrite(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed LastWrite");
            EventChangedLastWrite(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.LastWrite));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring security changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedSecurity(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed Security");
            EventChangedSecurity(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.Security));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the watcher responsible for monitoring size changes is 
        /// triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_ChangedSize(object sender, FileSystemEventArgs e)
        {
            Debug.WriteLine("EVENT - Changed Size");
            EventChangedSize(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem, NotifyFilters.Size));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when an internal watcher is disposed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_Disposed(object sender, EventArgs e)
        {
            Debug.WriteLine("EVENT - Disposed");
            EventDisposed(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.StandardEvent));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the main watcher detects an error (the watcher that detected the 
        /// error is part of the event's arguments object)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_Error(object sender, ErrorEventArgs e)
        {
            Debug.WriteLine("EVENT - Error");
            EventError(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.Error));
        }

        //--------------------------------------------------------------------------------
        /// <summary>
        /// Fired when the main watcher detects a file rename.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void watcher_Renamed(object sender, RenamedEventArgs e)
        {
            Debug.WriteLine("EVENT - Renamed");
            EventRenamed(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.Renamed));
        }

        //--------------------------------------------------------------------------------
        private void watcher_CreatedDeleted(object sender, FileSystemEventArgs e)
        {
            switch (e.ChangeType)   
            {
                case WatcherChangeTypes.Created :
                    Debug.WriteLine("EVENT - Created");
                    EventCreated(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem));
                    break;
                case WatcherChangeTypes.Deleted :
                    Debug.WriteLine("EVENT - Changed Deleted");
                    EventDeleted(this, new WatcherExEventArgs(sender as FileSystemWatcherEx, e, ArgumentType.FileSystem));
                    break;
            }
        }

......

在另一个文件B.cs中,主UI,我试图调用这些在A.cs中定义的事件响应函数,使用类似这样的东西:

void fileWatcher_EventCreated(object sender, WatcherExEventArgs e)
        {
            listView1.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, _fileWatcher.EventCreated());
    }

但我得到的错误是_fileWatcher.EventCreated()只能在+ =或 - = ...

的左侧

我试图用B.cs(UI的CS文件)做整件事,就像这样:

void fileWatcher_EventDeleted(object sender, WatcherExEventArgs e)
        {
            Action EventDeleted = delegate()
            {
                _lvie.fileName = ((FileSystemEventArgs)(e.Arguments)).FullPath;
                _lvie.fileEvent = "Deleted";
                _lvie.timeOfOccurance = DateTime.Now.ToString("HH:mm:ss.fff");
                listView1.Items.Add(_lvie);
            };

            listView1.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, EventDeleted);            
        }

但它没有很好地响应文件更改事件。它似乎没有选择一些事件。

我只是想知道我该怎么做:在主UI(A.cs)中调用后台线程(B.cs)中的响应事件函数?或者我应该以其他方式做到这一点?任何建议都非常感谢。谢谢。我对CS很新,所以请忍受我的无知。

1 个答案:

答案 0 :(得分:2)

Events只能从它们所在的类中提升。

B类不能引发A类中存在的事件。

您可以实现的最接近的解决方法是从A类中创建一个新的API函数,例如 - “RaiseMyEvent”,它从A类内部手动引发事件;从B类调用该函数。

public class A
{
    public event EventHandler MyEvent = null;

    public void RaiseMyEvent(EventArgs args)
    {
        var handler = MyEvent;
        if(handler != null)
        {
            handler(this, args);
        }
    }
}

//Then, from inside class B:
myInstanceOfA.RaiseMyEvent();  //This will cause A to raise its own event