更改 system.io.port datareceived 事件输出类型
我正在为 modbus 和串行连接构建一个类库,我需要返回一个字节数组,但是当使用 System.IO.Ports 中的 DataReceived 事件时,我无法返回任何字节,因为它的类型为 void。另外,我注意到 DataReceived 没有触发。以下是我的代码:
public void ConnectSerialModBus_Loopback(string COM, int baud, int meter_address, int function, int Code_HighByte, int Code_LowByte, int data_high_byte, int data_low_byte)
{
SerialPort port = new SerialPort(COM, baud);
try
{
if (!(port.IsOpen))
{
byte[] sendPacket = BuildPacket(meter_address, function, Code_HighByte, Code_LowByte, data_high_byte, data_low_byte);
double dataBytes = 2.0;
port.Open();
port.RtsEnable = false;//rts = high
port.Handshake = Handshake.None;
//SEND PACKET TO DEVICE
port.Write(sendPacket, 0, sendPacket.Length);
#region RECEIVE DATA FROM SERIAL
//MAKE DELAY TO SEND
Thread.Sleep(10);
port.RtsEnable = true;
//MAKE DELAY TO RECEIVE
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
//Thread.Sleep(CalculateDelay(dataBytes)+90);
port.Close();
port.Dispose();
#endregion
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (port != null)
{
if (port.IsOpen)
{
port.Close();
}
port.Dispose();
}
}
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort port = (SerialPort)sender;
byte[] readingbyte = new byte[port.BytesToRead];
if (port.BytesToRead > 0)
{
port.Read(readingbyte, 0, readingbyte.Length);
}
}
以某种方式,我想返回从 port_DataReceived
或从 ConnectSerialModBus_Loopback
接收到的字节,而且 DataReceived 也没有触发。请帮忙,这非常紧急
I am building a class library for modbus and serial connections, I need to return an array of bytes back but when using the DataReceived event from System.IO.Ports I cannot return any since it's type is void. Also, I am noticing that the DataReceived is not firing. The following is my code:
public void ConnectSerialModBus_Loopback(string COM, int baud, int meter_address, int function, int Code_HighByte, int Code_LowByte, int data_high_byte, int data_low_byte)
{
SerialPort port = new SerialPort(COM, baud);
try
{
if (!(port.IsOpen))
{
byte[] sendPacket = BuildPacket(meter_address, function, Code_HighByte, Code_LowByte, data_high_byte, data_low_byte);
double dataBytes = 2.0;
port.Open();
port.RtsEnable = false;//rts = high
port.Handshake = Handshake.None;
//SEND PACKET TO DEVICE
port.Write(sendPacket, 0, sendPacket.Length);
#region RECEIVE DATA FROM SERIAL
//MAKE DELAY TO SEND
Thread.Sleep(10);
port.RtsEnable = true;
//MAKE DELAY TO RECEIVE
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
//Thread.Sleep(CalculateDelay(dataBytes)+90);
port.Close();
port.Dispose();
#endregion
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (port != null)
{
if (port.IsOpen)
{
port.Close();
}
port.Dispose();
}
}
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort port = (SerialPort)sender;
byte[] readingbyte = new byte[port.BytesToRead];
if (port.BytesToRead > 0)
{
port.Read(readingbyte, 0, readingbyte.Length);
}
}
in some way I want to return the bytes received either from the port_DataReceived
or from the ConnectSerialModBus_Loopback
also the DataReceived is not firing. Please help this is very urgent
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
DataReceived 未触发
DataReceived 未触发,因为您在附加处理程序之后且在 SerialPort 的接收线程有机会运行之前立即调用了
port.Close()
。返回字节数组 - 简单答案
在您提供的简单代码示例中,您可以创建一个私有
Byte[]
成员并分配readingbyte
从您的port_DataReceived
事件处理程序中对其进行对象处理。返回字节数组 - OO 提示答案
但是,在更稳健的应用程序中,您应该考虑创建一个封装 Modbus ADU 协议部分的 Transaction 类,处理客户端请求的传输和(第2层)处理服务器的响应。
除了 ADU 层之外,您还可以将 PDU 层分离为抽象的 ModbusFunction 基类,该基类为 ADU 类提供接口以获取请求字节并返回响应字节。然后,您希望客户端使用的每个 modbus 功能都将在派生自 PDU 基类的自己的类中实现。
这样,当您需要与服务器交互时,您可以创建一个 PDU 函数类的实例,并使用适当的参数来形成正确的 PDU 数据包,并将其传递给处理请求/重试/响应逻辑的 Transaction 对象,将返回的数据传递回 PDU 对象以进行适当的解析。
向 PDU 基类添加事件将允许代码的其他部分附加到 PDU 类的事件,并在函数成功完成时接收通知。
对于具有多个可寻址属性(通过 Modbus 函数实现)的服务器,您可以为每个属性(或例如连续寄存器的一组属性)创建适当的 Modbus 函数类的实例,并附加到事件,从而更新您的模型和/或 UI 每当对象引发其更新事件时。如果您想要手动查询服务器,则挂钩 UI 命令以将 Properties Modbus Function 对象传递给 Transaction 对象;或者如果您希望定期轮询属性,则实现一个按计划执行此操作的计时器线程。
DataReceived is not firing
The DataReceived is not firing because you call
port.Close()
immediately after attaching the handler and before the SerialPort's receive thread has had a chance to run.Return an array of bytes back - Simple answer
In the simple code sample you provide, you could create a private
Byte[]
member and assign thereadingbyte
object to it from within yourport_DataReceived
event handler.Return an array of bytes back - OO hint answer
However, in a more rubust application, you should consider creating a Transaction class that encapsulates the Modbus ADU protocol parts, handling both the transmission of the client request and (layer 2) processing of the server's response.
In addition to the ADU layer, you would separate the PDU layer into an abstract ModbusFunction base class that provides an interface for the ADU class to get the request bytes and return the response bytes. Then each modbus function that you want your client to use will be realised in a class of its own that derives from the PDU base class.
That way, when you need to interact with the server you create an instance of a PDU function class, with the appropriate parameters to form the correct PDU data packet, and pass it to the Transaction object that handles the request/retry/response logic and passes the returned data back to the PDU object to parse appropriately.
The addition of an event to the PDU base class will allow other parts of your code to attach to the PDU class's event and receive notification when the function has completed succesfully.
With a server that has multiple addressable properties, implemented by way of Modbus functions, you would create an instance of the appropriate Modbus Function class for each property (or set thereof for contiguous registers, for example) and attach to the event, updating your Model and/or UI whenever the object raises its update event. Hook the UI commands to pass the Properties Modbus Function objects to the Transaction object if you want to query the server manually, or implement a timer thread that does it on a schedule if you want the properties to be polled on a regular basis.
不要休眠 datareceived 事件。
当事件触发时,将字节放入队列中。您将需要 UI 可用于将字节块重新组合在一起的方法。
请参阅 SerialPort101有关于此的更多详细信息。
Do not sleep the datareceived event.
When the event fires place the bytes in a queue. You will need methods that the UI can use to piece the chunks of bytes back together.
See SerialPort101 for more detail on this.