使用C#中的线程读取com端口 [英] Read com ports using threading in c#

查看:454
本文介绍了使用C#中的线程读取com端口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我是新手,所以我想在线程方面提供一些建议.我已经阅读了几篇有关在线线程的文章.

I would like some advise on threading as I'm new to it. I've read several articles on threading online.

我正在读取com端口数据.我想使用线程,这样它将每5秒读取一次数据并更新列表框上的数据.当前,正在读取所有数据. 我不确定从哪里开始.

I'm reading com ports data. I would like to use threading such that it will read the data every 5 seconds and update the data on the listbox. Currently, all the data is being read. I'm unsure where to start.

我应该在哪里开始放置线程代码?我正在使用Windows Form,c#VS2008.

Where shall i start putting my thread codes? I'm using Windows Form,c# VS2008.

这是我的代码,用于从com端口读取数据:

Here's my codes to read the data from com ports:

    void datareceived(object sender, SerialDataReceivedEventArgs e)
    {            
        myDelegate d = new myDelegate(update);
        listBox1.Invoke(d, new object[] { });

    }


    public void update()
    {           

        while (serialPortN.BytesToRead > 0)
            bBuffer.Add((byte)serialPortN.ReadByte());
        ProcessBuffer(bBuffer);

    }

    private void ProcessBuffer(List<byte> bBuffer)
    {            

        int numberOfBytesToRead = 125;

        if (bBuffer.Count >= numberOfBytesToRead)
        {            


                listBox1.Items.Add("SP: " + (bBuffer[43].ToString()) + "  " + " HR: " + (bBuffer[103].ToString()));


            // Remove the bytes read from the list
            bBuffer.RemoveRange(0, numberOfBytesToRead);

        }

    }        

谢谢!

推荐答案

为什么不使用计时器?将其放入适当形式的InitializeComponent方法中,

Why not use a timer? Put it into the InitializeComponent method of the form that is appropriate,

using System.Timers;

private void InitializeComponent()
{
    this.components = new System.ComponentModel.Container();
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.Text = "Form1";

    Timer timer = new Timer();

    timer.Interval = 5000;
    timer.Elapsed += new ElapsedEventHandler(TimerElapsed);

    //timer.Enabled = true; // you may need this, but probably not if you are calling the start method.
    timer.Start();
}

void TimerElapsed(object sender, ElapsedEventArgs e)
{
    // put your code here to read the COM port
}

此代码的唯一其他问题是您将获得异常跨线程操作无效.

The only other problem with this code is that you will get an exception Cross-thread operation not valid.

您将必须像这样修改您的代码,

You will have to modify your code like this,

private void ProcessBuffer(List<byte> bBuffer)
{
    int numberOfBytesToRead = 125;

    if (bBuffer.Count >= numberOfBytesToRead)
    {
        this.Invoke(new Action(() =>
        {
            listBox1.Items.Add("SP: " + (bBuffer[43].ToString()) + "  " + " HR: " + (bBuffer[103].ToString()));
        });

        // Remove the bytes read from the list
        bBuffer.RemoveRange(0, numberOfBytesToRead);
    }
}

原因是ProcessBuffer方法将在后台线程上运行.后台线程无法访问UI线程上的UI组件.因此,您必须调用此方法.调用该更新将在UI线程上的列表框中运行该更新.

The reason is that the ProcessBuffer method will be running on a background thread. Background threads cannot access UI components on the UI thread. So you have to call this.Invoke which will run that update to the listbox on the UI thread.

如果您想了解有关Invoke方法的更多信息,

Have a look here if you want to know more about the Invoke method,

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

更新:

因此,在TimerElapsed方法中,您将要调用代码,但是对我来说尚不清楚应调用代码的哪一部分? 数据接收"方法的作用是什么,在您的代码段中没有调用它的方法.

So within the TimerElapsed method you will want to call your code, but it is not clear to me which part of your code it should call? What is the 'datareceived' method for, there is nothing calling it in your code snippet.

所以我想就是这样

void TimerElapsed(object sender, ElapsedEventArgs e)
{
    Update();
}

public void Update()
{
    while (serialPortN.BytesToRead > 0)
        buffer.Add((byte)serialPortN.ReadByte());
    ProcessBuffer(buffer);
}

调用ProcessBuffer方法是没有意义的,因为缓冲区将从何处来?

It doesn't make sense for it to be calling the ProcessBuffer method because where will the buffer come from?

如果我的方法不正确,也许可以扩展您的代码示例,我很乐意提供更多帮助.

If I am not on the right track perhaps expand your code sample, and I am happy to help more.

请注意我对您的代码进行了一些样式更改(可以随意使用或保留它们),C#中的方法应以大写字母开头,并且在C#中调用变量bBuffer不是标准的.还有一点,如果仅从类内部调用该方法,则应将其设为私有.

Please note a few style changes I made to your code (feel free to take them or leave them), a method in C# should start with a capital letter, and calling the variable bBuffer is not standard in C#. Another point if that method is only called from within the class it should be made private.

这篇关于使用C#中的线程读取com端口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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