如何正确地触发自定义事件?

3

我需要一个自定义事件,如果在特定目录中发现/创建了一个新的/现有的文件,就会触发该事件。为了检查是否创建了新文件,我使用了SystemFileWatcher,它运行良好。为了检查程序启动时是否存在某些文件,我编写了一些代码并且也成功了。

我使用这个类作为事件参数:

public class FileDetectEventArgs : EventArgs
{
    public String Source { get; set; }
    public String Destination { get; set; }
    public String FullName { get; set; }

    public FileDetectEventArgs(String source, String destination, String fullName)
    {
        this.Source = source;
        this.Destination = destination;
        this.FullName = fullName;
    }
}

如果SystemFileWatcher引发了FileCreated事件,我会使用以下代码行:

如果SystemFileWatcher引发了FileCreated事件,我会使用以下代码行:

public void onFileCreated(object sender, FileSystemEventArgs e)
{
    // check if file exist
    if (File.Exists(e.FullPath))
    {
        OnNewFileDetect(new FileDetectEventArgs(source, destination, e.FullPath));  
    }
}

如果文件存在,我会尝试以以下方式触发事件:

public void checkExistingFiles(String source, String filter)
    {
        DirectoryInfo di = new DirectoryInfo(source);
        FileInfo[] fileInfos = di.GetFiles();
        String fileFilter = filter.Substring(filter.LastIndexOf('.'));       

        foreach (FileInfo fi in fileInfos)
        {
            if (fi.Extension.Equals(fileFilter))
            {
                OnNewFileDetect(new FileDetectEventArgs(source, destination, fi.FullName));                   
            }
        }
    }

这里是OnNewFileDetect事件:

protected void OnNewFileDetect(FileDetectEventArgs e)
    {
        if (OnNewFileDetectEvent != null)
        {
            OnNewFileDetectEvent(this, e);
        }
    }

问题在于,如果onFileCreated事件引发了我的OnNewFileDetect事件,一切都正常。但如果checkExistingFiles发现一些现有文件并尝试引发OnNewFileDetect事件,则什么也不会发生。我发现OnNewFileDetectEvent对象为空,因此什么也没发生。但是为什么当触发onFileCreated事件时它不为空呢?

2个回答

2

如果onFileCreated事件被触发,为什么它不是null?

在有订阅者之前,这个事件将是null。


顺便提一下,我建议考虑使用更好的模式来引发事件,并在此处使用标准的C#/.NET命名。这将更像:

// The event...
public EventHandler<FileDetectedEventArgs> NewFileDetected;

// Note the naming
protected void OnNewFileDetected(FileDetectedEventArgs e)
{
    // Note this pattern for thread safety...
    EventHandler<FileDetectedEventArgs> handler = this.NewFileDetected; 
    if (handler != null)
    {
        handler(this, e);
    }
}

感谢您的快速回复。 现在我遇到了错误:Delegate“FileDetecedEvent”不接受两个参数。 - thomas
@thomas 你的事件是如何声明的? - Reed Copsey
公共委托 void FileDetectEvent(object sender, FileDetectedEventArgs e); @Reed Copsey - thomas

1

@Reed Copsey回答了这个问题; 直到有订阅者,事件才会是null

此外,这是一个潜在的竞态条件:

if (OnNewFileDetectEvent != null)
{
    OnNewFileDetectEvent(this, e);
}

请注意,在多线程场景中,如果在if语句之后但在下一行调用之前将OnNewFileDetectEvent设置为null,则您的程序将崩溃。通常情况下,您应该这样做:
var del = OnNewFileDetectEvent;
if (del != null)
{
    del(this, e);
}

由于您的事件对象是不可变的,如果在if语句中不为null,则del永远不会为null。

还要注意您的命名方式不太常规。事件通常不以On为前缀,调用事件的方法才会这样命名。


好的,谢谢你。但是为什么我现在会得到错误提示:“Delegate“FileDetecedEvent”不接受两个参数”? - thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接