繁体   English   中英

C# EventHandler 调用并不总是有效

[英]C# EventHandler invoke doesn't always work

我有一个带有以下代码的类:

    public delegate void EventHandler(HMIEventArgs e);
    public event EventHandler OnEvent;

    private void ReadReg(RegisterMap register)
    {
        if (!_hmiConnected) return;
        var eventArgs = new HMIEventArgs();

        var handler = OnEvent;

        try
        {
            byte slaveId = 1;
            ushort startAddress = register.Register;

            eventArgs.Event = Events.GotData;
            eventArgs.IPAddress = _hostname;
            eventArgs.Name = register.FriendlyName;

            ushort[] val = _master.ReadHoldingRegisters(slaveId, startAddress, 1);
            eventArgs.Data = val[0];
            handler?.Invoke(eventArgs);

            // -------- THIS GETS PRINTED ------------
            Debug.WriteLine("Got data from " + _hostname + ":" + register.Register + "(" + register.FriendlyName + ") : " + val[0]);
            
        }
        catch (Exception err)
        {
            Debug.WriteLine(err.ToString());                
        }
    }

这个类的几个实例是在另一个类中创建的:

        new Thread(() =>
        {
            tasks.Add(Task.Factory.StartNew(() =>
            {
                _masters.Add(new HMIMaster().Connect(ipAddress, port).SetRegisters(registers));

                _masters.Last().OnEvent += HMIEvent;

                Debug.WriteLine(_masters.Count + " masters");
            }));

        }).Start();


    private static void HMIEvent(HMIEventArgs e)
    {

        // HOWEVER THIS SOMETIMES DOESN'T SHOW FOR 
        // ALL INSTANCES OF THE PREVIOUS CLASS

        Debug.WriteLine(">> in logger (" + e.IPAddress + " " + e.Event + ") >> " + e.Name + " :: " + e.Data);
        var handler = OnEvent;
        handler?.Invoke(e);
    }

我在这里做错了吗?

我会使用静态事件来避免每次在新实例上注册并在处置时取消注册(以避免内存泄漏)。 在您的情况下不需要锁定,所以我会像这样简化它:

(一级)

public static event EventHandler<HMIEventArgs> HMIEvent;
private void OnHMIEvent(HMIEventArgs e)
{
    HMIEvent?.Invoke(this, e);
}

private void ReadReg(RegisterMap register)
{
    ...
    OnHMIEvent(new HMIEventArgs()
    {
        Name = register.FriendlyName,
        Event = Events.GotData,
        IPAddress = _hostname,
        eventArgs.Data = val[0]
    });
    ...
}

(二等)


...
FirstClass.HMIEvent += FirstClass_HMIEvent; // Probably in your static constructor, register only once (unregister if required on disposal)
...

private void FirstClass_HMIEvent(object sender, HMIEventArgs e)
{
// (FirstClass)sender can be used here if required
}

顺便说一句,您的示例代码中的这两行不应该存在(在您的静态 HMIEvent 方法中,您没有向我们提供第二类的 OnEvent 是什么,并且您不需要每次都将它传递给处理程序 var):

var handler = OnEvent;
handler?.Invoke(e);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM