我正在尝试练习文件监视的示例。因此,基本思想是创建一个独立的线程来监视监视文件夹中的任何事件。原始程序是基于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很新,所以请忍受我的无知。
答案 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