【问题标题】:How to change an event handler callback dynamically如何动态更改事件处理程序回调
【发布时间】:2012-01-11 08:53:06
【问题描述】:

我有一个串口通信类,里面有以下代码(除其他外,只显示相关部分):

public Form1 m_parent;
private delegate void ProcessPacketDelegate(byte[] packet);
public SerialPort comPort = new SerialPort();

//Constructor code
....setting baudrate, portname etc.
... setting m_parent as the main form
...setting other things

//add an event handler
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
//constructor code end

void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        int bytes = comPort.BytesToRead;
        byte[] comBuffer = new byte[bytes];
        comPort.Read(comBuffer, 0, bytes);
        comPort.DiscardInBuffer();
        m_parent.Invoke(new ProcessPacketDelegate(m_parent.ProcessPacket), comBuffer);
}

我正在从我的主窗体中实例化这个类,该地址存储在 m_parent 中。主窗体有一个名为 ProcessPacket 的方法,用于处理传入的数据包。到目前为止一切顺利。

现在,我想处理 2 个串行端口,所以我需要 2 个此类的实例。但是,我不希望他们使用可能导致数据包冲突的相同 ProcessPacket 方法。我想以这样的方式修改串行端口通信类,即在构造函数中或通过getsets我会动态设置回调方法,因此实例#1将调用m_parentProcessPacket_A,实例#2将调用m_parentProcessPacket_B。不幸的是,这似乎超出了我的 .NET 技能,所以任何帮助都会很棒! 谢谢!

【问题讨论】:

  • 两个串口 == 两个 DataReceived 事件。只需将通用代码移动到私有辅助方法中即可。顺便说一句,从不在数据读取方法中调用 DiscardInBuffer(),这只会导致无法诊断的数据丢失。
  • 你的意思是 DiscardInBuffer 可以刷新缓冲区,而前面的代码行 - comPort.Read(...) - 还没有完成?
  • 驱动程序与您的事件处理程序异步运行。您将丢弃在 Read 调用后一纳秒收到的字节。

标签: c# .net delegates callback serial-port


【解决方案1】:

您可以在构造函数中定义一个变量并使用它。

if(condition)
   handler =  comPort_DataReceived;
else
   handler =  comPort_SomeElseMethod;

然后绑定这个

comPort.DataReceived += handler

【讨论】:

  • 谢谢!不是我真正想要的,而是一个很好的解决方法。
【解决方案2】:

有一个这样的构造函数:

YourClass(ProcessPacketDelegate process_packet)
{
    // ...
    this.process_packet = process_packet;
}

在你的课堂上,还有:

ProcessPacketDelegate process_packet;

然后在你的comPort_DataReceived 做:

m_parent.Invoke(this.process_packet, comBuffer);

在你实例化你的类时在你的主窗体中:

instance1 = new YourClass(new ProcessPacketDelegate(this.ProcessPacket_A));
instance2 = new YourClass(new ProcessPacketDelegate(this.ProcessPacket_B));

【讨论】:

  • 非常感谢!我按照您建议的方式修改了我的课程,但停留在主表单上,因为在 Intellisense 下方的行中发现了一个错误,例如:'字段初始化程序无法引用非静态字段,方法...' instance1 = new YourClass(new ProcessPacketDelegate(ProcessPacket_A ));试图把'public delegate void ProcessPacketDelegate(byte[] packet);'上面一行,但无济于事。
猜你喜欢
  • 2010-09-19
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多