首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实时绘制几个图表,C#窗体

实时绘制几个图表,C#窗体
EN

Stack Overflow用户
提问于 2014-03-15 12:25:41
回答 1查看 3K关注 0票数 6

我想得到一个预览从我的16个通道的A/C和我需要刷新频率在25-40赫兹(更新每25-40毫秒)。我做了几个线程和计时器的组合,但我只在最多4个图表中实现了令人满意的性能。在扩展了图表的刷新范围后,添加图表的帧速率约为0.5/s,我采用了fastline图。

我每隔20毫秒就用计时器从A/C中获取新的数据。经过一些测试后,似乎添加了一个单独的线程来处理每个图表,它会在给定的时间内休眠,然后更新绘图,这是没有效率的(至少以我的方式)。

所以问题是:如何有效地处理多个图表。

下面我介绍了代码中最重要的部分。

代码语言:javascript
运行
复制
    System.Timers.Timer tim = new System.Timers.Timer(20);
    System.Threading.Thread[] t;
    int HighChan = 15;
    //button which runs the preview, executed once
    private void previewB_Click(object sender, EventArgs e)
    {                                            
        t = new System.Threading.Thread[HighChan + 1];
        for (int i = 0; i <HighChan+1; i++)
        {                    
            charts[i].Series.SuspendUpdates();
            //run a separate thread for each chart
            t[i] = new System.Threading.Thread(new ParameterizedThreadStart(updatePlot));
            t[i].Start(i);                    
        }

        //run timer to get new data with tim.interval                    
        tim.Stop();               
        tim.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);           
        tim.Start();                                
    }

    ushort[] ADData_prev;
    //get new data from A/C every tim.interval
    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields
        // I also tried to suspend and resume threads t from this place but unsuccessfully
    }


    //update the chart with new data
    void updatePlot(object chart_info)
    {          
        int i = (int)chart_info;

        while(true)
        {
                //wait for new data to read
                Thread.CurrentThread.Join(20);

                charts[i].Invoke(new Action(delegate()
                { charts[i].ResetAutoValues(); }));

                // I skipped some conditions to make code clearer                              
                //remove old point and add new one
                charts[i].Invoke(new Action(delegate()
                {
                    charts[i].Series[0].Points.RemoveAt(0);
                    charts[i].Series[0].Points.AddY(ADData_prev[i]);
                }));                     

                charts[i].Invoke(new Action(delegate()
                {
                    charts[i].Series.ResumeUpdates();
                    charts[i].Series.Invalidate();
                    charts[i].Series.SuspendUpdates();
                }));

          }
    }

更新:

1.我已经将updatePlot()的功能移到timer的onTimedEvent中,因此现在看起来如下:

代码语言:javascript
运行
复制
    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields

        charts[0].Invoke(new Action(delegate()
        {

           for (int i = 0; i < HighChan + 1; i++)
           {
               //charts[i] stuff here
           }
        }
    }

2.我决定更改onTimedEvent中的bool变量,该变量允许绘制图表一次,每个计时器在updatePlot()中的while(true)循环中勾选一次:

代码语言:javascript
运行
复制
    private void previewB_Click(object sender, EventArgs e)
    {                                            
        for (int i = 0; i <= HighChan; charts[i++].Series.SuspendUpdates()) ;
        t = new System.Threading.Thread(updatePlot);
        t.Start();

        //run timer to get new data with tim.interval                    
        tim.Stop();               
        tim.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);           
        tim.Start();                                
    }

    bool entry = false;
    private void OnTimedEvent(object sender, EventArgs e)
    {
        ADData_prev = getPrev();  //gets new data, array wit 16 fields
        entry = true;            
    }

    void updatePlot()
    {
       while(true)
       {
          if(entry)
          {
               charts[0].Invoke(new Action(delegate()
               {
                  for (int i = 0; i < HighChan + 1; i++)
                  {
                     //charts[i] stuff here
                  }
               }
          entry = false;
          }
       }
    }

这些解决办法只作了很小的改进。不幸的是,在这两种情况下,图表刷新不够快。另外,来自charts[]阵列的前8帧速度非常快,而最后8的帧速率约为0.5Hz,这对我来说很奇怪,因为它们的行为方式不同。

更新2:

在第一篇文章中,我需要每20-40毫秒重新绘制一次图表。当我只绘制一幅图时,我可以达到这个帧速率,所以这不是数据收集时间的问题( A/C工作在Fs=1k Hz的背景下)。也许将队列绑定到图表可以使其速度更快,但不会太大。

我将更准确地描述在我进行的性能测试中发生了什么。

因此,当我将nr (图数刷新)限制为6,用ti (时间间隔)20 50更新它们时,它们一次存储点数(np) =50,它们都运行平稳。但是,当我将np改为100时,只有图表1-4运行平稳,当5的速度非常慢,6几乎停止。当nr = 6,ti = 20,np = 250时,图1-3运行平滑,图4-6运行速度为0.1fps。

当nr = 10,ti = 20,np = 50时,图表1-6的行为方式与在nr=6情况下相同,而图7-8令人惊讶地运行平稳,9-10类似于1fps。当nr = 10,ti = 20,np = 100时,图表1-6的表现方式与nr=6情况相同(因此只有图表1-3运行平稳),而图表7-8仍运行平稳,9-10则为0.1fps。

当nr = 16,ti = 20,np = 50时,图1-8在nr=10情况下表现为相似,其他8则为0.05fps或其他什么。

无论我使用哪种方法,对于单线程、多个线程、单个/多个调用、队列绑定、Thread.Sleep()、Threed.CurrentThread.Join()、定时器、异步,结果总是不太一样。老实说,我不知道是什么原因,我不能获得实时数据预览16快行图表。

我会感谢你的任何建议。

EN

回答 1

Stack Overflow用户

发布于 2014-03-15 12:32:27

老实说,我不认为多线程会对你有任何帮助。最后,最重要的操作将是更新图表,无论如何,这必须在UI线程上完成。

我建议您有一个线程,它每20 at获取所有最新值,然后在UI上调用单个Invoke,在单个Action中一次更新所有图表。每次更新多次调用会导致严重的性能损失。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22423779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档