【发布时间】:2010-11-01 16:45:26
【问题描述】:
我有一些 SerialPort 代码经常需要从串行接口(例如 COM1)读取数据。但这似乎是 CPU 密集型的,如果用户移动窗口或向窗口显示大量数据(例如通过串行线路接收的字节),那么通信就会混乱。
考虑以下代码:
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer = new byte[port.ReadBufferSize];
var count = 0;
try
{
count = port.Read(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
if (count == 0)
return;
//Pass the data to the IDataCollector, if response != null an entire frame has been received
var response = collector.Collect(buffer.GetSubByteArray(0, count));
if (response != null)
{
this.OnDataReceived(response);
}
需要收集代码,因为数据流是恒定的 并且必须针对(帧/数据包)分析数据。
port = new SerialPort();
//Port configuration code here...
this.collector = dataCollector;
//Event handlers
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
如果没有用户交互并且没有任何内容添加到窗口中, 这很好用,但是一旦有交互,沟通就会变得一团糟。 发生超时等......
例如,这会搞砸一切:
Dispatcher.BeginInvoke(new Action(() =>
{
var builder = new StringBuilder();
foreach (var r in data)
{
builder.AppendFormat("0x{0:X} ", r);
}
builder.Append("\n\n");
txtHexDump.AppendText(builder.ToString());
txtHexDump.ScrollToEnd();
}),System.Windows.Threading.DispatcherPriority.ContextIdle);
});
但即使是对 log4net 的简单调用也会导致问题。
是否有优化 SerialPort 通信的最佳实践 或者有人可以告诉我我做错了什么......
更新:
如果以上没有多大意义。我做了一个非常简单(也很愚蠢)的小例子:
class Program
{
static void Main(string[] args)
{
var server = new BackgroundWorker();
server.DoWork += new DoWorkEventHandler(server_DoWork);
server.RunWorkerAsync();
var port = new SerialPort();
port.PortName = "COM2";
port.Open();
string input = "";
Console.WriteLine("Client on COM2: {0}", Thread.CurrentThread.ManagedThreadId);
while (input != "/quit")
{
input = Console.ReadLine();
if (input != "/quit")
{
var data = ASCIIEncoding.ASCII.GetBytes(input);
port.Write(data, 0, data.Length);
}
}
port.Close();
port.Dispose();
}
static void server_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Listening on COM1: {0}", Thread.CurrentThread.ManagedThreadId);
var port = new SerialPort();
port.PortName = "COM1";
port.Open();
port.ReceivedBytesThreshold = 15;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var port = (SerialPort)sender;
int count = 0;
byte[] buffer = new byte[port.ReadBufferSize];
count = ((SerialPort)sender).Read(buffer, 0, buffer.Length);
string echo = ASCIIEncoding.ASCII.GetString(buffer,0,count);
Console.WriteLine("-->{1} {0}", echo, Thread.CurrentThread.ManagedThreadId);
}
}
结果可能如下所示:
在 COM1 上监听:6 COM2 上的客户端:10 这是我发送的一些示例数据 ---> 6 这是我发送的一些示例数据
所以从端口读取数据发生在主线程上......
这可能是导致我的问题的部分原因吗?
【问题讨论】:
-
最后一段代码在哪里调用? “数据”变量从何而来?
-
当 IDataCollector 引发事件以指示它收集了一整帧数据时,将调用上面的代码。它在 WPF 窗口中。但是,即使您在 IDataTransportServer 或 IDataCollector 实现的代码中添加 log.Warn(".....") 语句,SerialCommunication 也会被搞砸......“数据”只是我们从串行线路中读取的内容: buffer.GetSubByteArray(0, count)
-
几乎任何代码都会导致串行通信出错...
标签: c# .net performance serial-port