【问题标题】:Serial Data, threading, and check boxes串行数据、线程和复选框
【发布时间】:2013-01-27 18:02:31
【问题描述】:

我正在为物理课做一个项目,并想尝试将一个应用程序放在一起来执行以下操作。测试单元上有一个串行端口,以 1 Hz 的频率输出数据。我想要一个可以读取串口数据并将其保存到文件的应用程序。我在控制台应用程序中创建了它,它工作正常。现在,我想要一个 GUI。在 GUI 的主屏幕上,我想要几个复选框。一种是用户可以在传入的数据流中添加时间戳,一种是将数据输出到文本文件,一种是将数据发送到我的石墨图形服务器。

所以,我在这里寻找一些指示。现在,我有一个连接按钮。按下时,它会打开串行端口并执行 serial.readline() 但如果当前没有数据通过链接推送,则应用程序被锁定。所以我假设我需要使用线程。这听起来正确吗?

最后,如何处理复选框?我想要总共 4 个按钮。连接/断开记录/暂停。至少这是我的想法。

【问题讨论】:

    标签: c# multithreading checkbox


    【解决方案1】:

    无需为串行端口创建线程,只需挂钩DataReceived 事件即可。

    至于复选框挂钩到CheckedChanged 事件。

    所以它看起来像:

    private bool paused;
    private SerialPort sp;
    
    public Form1()
    {
        InitializeComponent();
    
        sp = new SerialPort();
        sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
    }
    
    private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        if (!paused)
        {
            string indata = sp.ReadExisting();
    
            //Display the data
            //To avoid cross thread problems do something like this
            Invoke(new Action(() =>
            {
                textBox1.Text += indata;
            }));
    
            //Or if you are just writing to the console 
            Console.WriteLine(indata); //Thread safe
    
            //Timestamp checkbox
            if (checkBox3.Checked)
            {
                //Display timestamp using DateTime.Now  
            }
    
        //Write to file checkbox
        if (checkBox4.Checked)
        {
            using (StreamWriter file = new StreamWriter(path, true))
            {
                file.WriteLine(indata);
            } 
        }
    }
    }
    
    //Pause/Resume Checkbox
    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        paused = checkBox1.Checked;
    }
    
    //Connect/Disconnect checkbox
    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox2.Checked)
        {
            sp.Open();
        }
        else
        {
            sp.Close();
        }
    }
    

    【讨论】:

    • 我怀疑 DataReceived 实际上会在后台线程上引发,因此您需要编组命令以将 UI 控件更新到 UI 线程。
    • 不要在DataReceived事件处理程序中使用Invoke,当UI线程关闭端口时很可能导致死锁。仅使用 BeginInvoke。此代码调用的高速率进一步使得 UI 线程很可能会冻结。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多