【问题标题】:How to raise custom event correctly?如何正确引发自定义事件?
【发布时间】:2012-04-10 23:41:46
【问题描述】:

如果找到/创建了特定目录中的新/现有文件,我需要一个自定义事件。为了检查是否创建了新文件,我使用了 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 事件,我将使用以下代码行:

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-Event 引发我的 OnNewFileDetect-Event 一切正常。但是,如果 checkExistingFiles 发现一些现有文件并尝试引发 OnNewFileDetect-Event,则不会发生任何事情。我发现 OnNewFileDetectEvent-Object 为空,所以什么也没发生。但是如果 onFileCreated-Event 被触发,为什么它不为空呢?

【问题讨论】:

    标签: c# events


    【解决方案1】:

    但是如果 onFileCreated-Event 被触发,为什么它不为空?

    在订阅该事件之前,此事件将为空。


    附带说明,我会考虑切换到更好的模式来引发事件,以及在此处使用标准 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);
        }
    }
    

    【讨论】:

    • 感谢您的快速答复。现在我得到错误:委托“FileDetecedEvent”不接受两个参数
    • @thomas 您的活动是如何宣布的?
    • 公共委托 void FileDetectEvent(object sender, FileDetectedEventArgs e); @Reed Copsey
    【解决方案2】:

    @Reed Copsey 回答了这个问题;该事件将是null,直到它有订阅者。

    另外,这是一个潜在的竞争条件:

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

    请注意,在多线程场景中,如果在if 语句之后、下一行调用之前将OnNewFileDetectEvent 设置为null,您的程序将崩溃。通常你会这样做:

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

    由于您的事件对象是不可变的,delif 语句中不为 null 时将永远不会为 null。

    另请注意,您的命名是非常规的。事件通常不以On 为前缀,调用事件的方法是。

    【讨论】:

    • 好的,谢谢你,但为什么我现在得到错误:委托“FileDetecedEvent”不接受两个参数
    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    相关资源
    最近更新 更多