Tim*_*hyP 3 .net c# performance serial-port
我有一些常常需要从串行接口(例如COM1)读取数据的SerialPort代码.但这似乎是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);
}
Run Code Online (Sandbox Code Playgroud)
需要收集代码,因为数据流是恒定的,并且必须分析数据(帧/分组).
port = new SerialPort();
//Port configuration code here...
this.collector = dataCollector;
//Event handlers
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
Run Code Online (Sandbox Code Playgroud)
如果没有用户交互并且没有任何东西被添加到窗口,这可以正常工作但是只要有交互通信就会搞砸了.超时发生等......
例如,这会搞砸一切:
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);
});
Run Code Online (Sandbox Code Playgroud)
但即使是对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);
}
}
Run Code Online (Sandbox Code Playgroud)
结果可能如下所示:
在COM2上监听COM1:6客户端:10这是我发送的一些示例数据---> 6这是我发送的一些示例数据
因此,从端口读取数据发生在主线程上....
这可能是造成我问题的部分原因吗?
小智 14
我很惊讶没有人抓到这个.使用DataReceived事件时,SerialPort类使用自己的线程.这意味着,例如,如果订阅者正在访问任何Form元素,则必须使用Invoke或BeginInvoke方法来完成.否则,您最终会进行跨线程操作.在.net的旧版本中,这会被不可预知的行为(取决于PC中的CPU核心)忽视,并且在以后的版本中,应该引发异常.
| 归档时间: |
|
| 查看次数: |
24388 次 |
| 最近记录: |