【发布时间】:2020-05-18 09:04:58
【问题描述】:
我已经使用 WPF 制作了应用程序,我必须实现串行通信。 Bellow 我有 DataReceived 功能。
主要问题是该函数仅在某些时候触发,有没有人有更好的解决WPF中DataReceived触发的方法?
下面是连接到 ComPort 的连接
public static void connnect(string recPort)
{
System.Windows.Threading.DispatcherTimer MyTimer = null;
bool error = false;
String serialpname = recPort;
ComPort = new SerialPort();
if (ComPort.IsOpen == false)
{
ComPort.PortName = serialpname;
ComPort.BaudRate = 38400;
ComPort.Parity = Parity.None;
ComPort.DataBits = 8;
ComPort.StopBits = StopBits.One;
ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived);
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += dispatcherTimer_Tick;
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
try
{
if (ComPort.IsOpen == false)
{
//Open Port
ComPort.Open();
dispatcherTimer.Start();
}
}
catch (System.IO.IOException) { error = true; }
}
}
下面是询问端口的定时器
private static void dispatcherTimer_Tick(object sender, EventArgs e)
{
try
{
ComPort.Write(eot + "11" + STX + "2170" + ENQ); // get pos
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
数据接收事件
public static void OnSerialDataReceived(object sender,
SerialDataReceivedEventArgs args)
{
bool isString = true;
try
{
Thread.Sleep(100);// this solves the problem
byte[] readBuffer = new byte[ComPort.ReadBufferSize];
int readLen = ComPort.Read(readBuffer, 0, readBuffer.Length);
string readStr = string.Empty;
if (isString)
{
readStr = Encoding.Default.GetString(readBuffer, 0, readLen);
if(readStr.Length > 10)
{
if (readStr.StartsWith("\u0002"))
{
Position = (Mid(readStr, 2, 5));
Messenger.Default.Send("NewPos");
}
else
{
Position = (Mid(readStr, 31, 4));
Messenger.Default.Send("NewPos");
}
}
}
else
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < readLen; i++)
{
stringBuilder.Append(readBuffer[i].ToString("X2") + " ");
}
readStr = stringBuilder.ToString();
}
}
catch (Exception ex)
{
Trace.TraceError(ex.Message);
Console.WriteLine(ex);
}
}
【问题讨论】:
-
与大多数基于事件的 I/O 一样,您可能应该养成编写立即需要的代码并将其余部分留给另一个线程处理的习惯。否则,如果您花费太多时间进行计算或其他形式的 I/O(例如
Messenger.Default.Send)并且花费的时间太长,您可能会遇到 缓冲区溢出错误,从而导致数据丢失。如果您花费的时间过长,发件人也可能会遇到超时。因此,例如,您可以读取 COM 数据并将其存储并从回调中快速返回 -
...或者实际使用
asyncI/O。即使ComPort类没有明确的async支持,端口的BaseStream支持。 stackoverflow.com/a/32436104/585968。这种方法比摆弄队列要好得多:) -
感谢您的回答,我已经删除了其他 I/O 和其他 I/O 表单,但 DataReceived 的问题仍然存在。据我所见,如果我在函数中放置一个断点,它会正常工作。
-
你能把你设置
ComPort的代码贴出来吗?特别是波特率、奇偶校验、流量控制等。还有你在和什么类型的设备说话? -
请edit您的问题包含该信息
标签: c# wpf serial-port communication