Bri*_*ker 5 c# charts multithreading timer
我想从A / C的16个通道中获取预览,我需要25-40Hz的刷新率(每25-40ms更新一次)。我很少使用线程和计时器的组合,但仅在最多4个图表上就获得了令人满意的性能。在扩展图表范围以刷新后,添加的图表的帧速率约为0.5 / s。我应用了快速折线图。
我应用了一个计时器,每20毫秒从A / C获取新数据。经过一些测试,看起来添加一个单独的线程来处理每个图表(在给定时间内休眠,然后更新绘图)效率不高(至少按照我的方式)。
所以问题是:如何有效地处理多个图表。
下面,我介绍了代码的最重要部分。
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();
}));
}
}
Run Code Online (Sandbox Code Playgroud)
更新:1.
我已经将updatePlot()的功能移到了计时器的onTimedEvent上,所以现在看起来像这样:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
2.我决定在onTimedEvent中更改bool变量,该变量允许绘制一次图表,每个计时器的周期都在updatePlot()的while(true)循环中:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些解决方案仅做了很小的改进。不幸的是,在两种情况下,图表的刷新速度都不够快。另外,Charts []数组中的前8个刷新速度很快,而后8个具有约0.5 Hz的帧速率,这对我来说很奇怪,因为它们的行为方式不同。
更新2:
如第一篇文章所述,我需要每20-40ms重绘一次图表。当我只绘制一个图时,我可以达到该帧速率,因此与数据收集时间无关(A / C在Fs = 1k Hz的背景下工作)。也许将队列绑定到图表可以使其速度更快,但幅度却不大。
我将更精确地描述我进行的性能测试中发生了什么。
因此,当我将nr(要刷新的图表数)限制为6时,以ti(时间间隔)20ms更新它们,因此它们一次存储点数(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或类似的值。
无论我使用哪种方法,对于单线程,多线程,单次/多次Invoke,队列绑定,Thread.Sleep(),Threed.CurrentThread.Join(),Timer,异步,结果总是不一样。老实说,我不知道为什么无法在16条快速折线图上获得实时数据预览。
我将感谢您的任何建议。
老实说,我不认为多线程在这里对你有任何帮助。归根结底,最繁重的操作将是更新图表,无论如何,这都必须在 UI 线程上完成。
我建议您使用一个线程,每 20 毫秒获取一次所有最新值,然后Invoke在 UI 上调用一个线程,该线程在单个Action. 每次更新调用多次会导致显着的性能损失。