C#,在单独的线程中解析数据并更新GUI

时间:2015-10-16 09:39:59

标签: c# .net multithreading user-interface backgroundworker

大家。基本上我想要实现的工作流程如下:

  • 从COM端口接收大量数据;
  • 将它们保存到ListBox;
  • 从ListBox异步读取行并将它们解析为浮点数组;
  • 在两个单独的Charts;
  • 上绘制数据

由于截止日期不是到目前为止,我从一个名为Termie的开源项目开始,该项目实现了一个简单的串行接口,也提供了直接开箱即用的通信配置表单。 要执行多线程操作,我使用BackgroundWorker

private BackgroundWorker backgroundPressure = new BackgroundWorker();

我在我的主要表单的构造函数方法中初始化:

public consoleForm()
{
    ...
    // Initialize background worker to separate GUI from data collection
    backgroundPressure.DoWork += new DoWorkEventHandler(backgroundPressure_DoWork);
    backgroundPressure.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundPressure_RunWorkerCompleted);
    backgroundPressure.ProgressChanged += new ProgressChangedEventHandler(backgroundPressure_ProgressChanged);
    backgroundPressure.WorkerReportsProgress = true;
    backgroundPressure.WorkerSupportsCancellation = true;
}

传输开始时,将调用backgroundPressure的RunworkerAsync方法:

if(!backgroundPressure.IsBusy)
{
    backgroundPressure.RunWorkerAsync();
}

正确处理DoWork事件,我的程序正确输入了具有以下代码的处理程序方法:

    protected void backgroundPressure_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker sendingWorker = (BackgroundWorker)sender;

        BeginInvoke((MethodInvoker)delegate
        {
            pressureChart.Series.Clear();
            pressureData.Clear();
            timeAxis.Clear();

            foreach (string name in pressureSensorNames)
            {
                pressureChart.Series.Add(name);
            }
        });

        Stopwatch sto = new Stopwatch();
        int linenumber = syncWithLogger("pres");

        int debugs = linenumber;

        while (linenumber == -1)
        {
            Thread.Sleep(100);
            BeginInvoke((MethodInvoker)delegate
            {
                linenumber = syncWithLogger("pres");
            });
        }

        sto.Start();

        long elapsed = sto.ElapsedMilliseconds;

        while (!sendingWorker.CancellationPending)
        {
            BeginInvoke((MethodInvoker)delegate
            {
                try
                {
                    elapsed = sto.ElapsedMilliseconds;

                    pressureChartUpdate(linenumber, elapsed);
                    imuChartUpdate(linenumber + 1, elapsed);

                    linenumber += 2;
                    Thread.Sleep(100);
                }
                catch(Exception ex)
                {
                    if(ex is FormatException)
                    {
                        Thread.Sleep(100);
                        // Wait and go on
                    }
                    else if(ex is ArgumentOutOfRangeException)
                    {
                        Thread.Sleep(100);
                        // Wait and go on
                    }
                }

            });

            sendingWorker.ReportProgress(10, 100);

            BeginInvoke((MethodInvoker)delegate
            {
                samplesAcquiredStatus.Text = sto.ElapsedMilliseconds.ToString();
            });


            e.Cancel = true;
            sto.Stop();

        }
    }

while (!sendingWorker.CancellationPending)区块之前,一切都运作良好。当它进入时,GUI冻结,Visual Studio报告内存占用的渐进和快速增加,我真的不理解,而没有抛出异常。

Memory occupation increase

如果我注释掉调用GUI更新方法的代码

,也会发生这种行为
pressureChartUpdate(linenumber, elapsed);
imuChartUpdate(linenumber + 1, elapsed);

我已经单独测试过解析器,所以我认为问题在于多线程操作。任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

一个问题是在UI线程上调用Thread.Sleep。这将根据定义阻止您的UI并使其无响应。一旦它处于睡眠状态,它就无法执行任何操作。