System.IO.Ports.SerialPort和多线程 [英] System.IO.Ports.SerialPort and Multithreading

查看:368
本文介绍了System.IO.Ports.SerialPort和多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些的SerialPort code,它不断地需要从一个串行接口(例如COM1)读取数据。但是,这似乎是非常CPU密集型,如果用户移动窗口或大量的数据正在显示的窗口(如接收串行线路上的字节数),那么通信被搞砸了。

I have some SerialPort code that constantly needs to read data from a serial interface (for example COM1). But this seems to be very CPU intensive and if the user moves the window or a lot of data is being displayed to the window (such as the bytes that are received over the serial line) then communication gets messed up.

考虑以下code:

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);
}

的code需要被收集数据的流是恒定 和数据已为(帧/分组)进行分析。

The code needs to be collected as the stream of data is constant and the data has to be analyzed for (frames/packets).

    port = new SerialPort();

    //Port configuration code here...

    this.collector = dataCollector;

    //Event handlers
    port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    port.Open();

如果没有用户交互和没有被添加到窗口, 这工作正常,但只要有互动的沟通真的得到弄糟。 发生超时等...

If there is no user interaction and nothing being added to the window, this works fine but as soon as there is interaction communication really gets messed up. Timeouts occur etc....

例如,这一切都打乱了:

For example, this messes everything up:

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的原因的问题。

But even simple calls to log4net cause problems.

是否有优化的SerialPort通信的任何最佳实践 或者有人可以告诉我,我在做什么错了......

Are there any best practices to optimize SerialPort communication or can someone tell me what I'm doing wrong...

更新:

如果上面没有太大的SENCE。我做了一个非常简单(愚蠢)小例子:

In case the above didn't make much sence. I made a very simple (and stupid) little example:

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);
    }
}

其结果可能是这样的:

The result might look like this:

上侦听COM1:6 客户端上的COM2:10 这是一些我送样本数据 ---> 6这是一些我送样本数据。

Listening on COM1: 6 Client on COM2: 10 This is some sample data that I send ---> 6 This is some sample data that I send

所以从端口读取数据恰好在主线程上......

So reading the data from the port happens on the main thread....

也许这是一个什么样的原因造成我的问题的一部分?

Might this be part of what's causing my problems?

推荐答案

您最后的结论,该事件在主线程上运行,可能不是真正的Windows应用程序。不要在一个控制台中进行测试。

Your last conclusion, that the event runs on the Main thread, may not be true for Windows App. Don't test this in a Console.

正确的方法来调整,这是:

The proper way to tune this is:

  • 设置一个足够大的缓冲区,虽然最低4096,通常确定

  • set a large enough buffer, although the minimum 4096 is usually Ok

设置ReceivedBytesThreshold高达容忍的(并做到这一点的之前打开())

set the ReceivedBytesThreshold as high as tolerable (and do it before the Open())

做到尽量少在接收到的事件,传递 数据队列或MemoryStream的,如果你需要更多的时间

do as little as possible in the Received event, pass the data to a Queue or MemoryStream if you need more time

这篇关于System.IO.Ports.SerialPort和多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆