你好,我正在尝试创建一个应用程序,它可以读取数据,处理它并在图形上实时绘制它,直到我按下停止应用程序读取和处理更多数据的ESC。我在Visual ++/CLR中创建了这个应用程序:
我的实时数据处理与绘图应用
当我单击按钮时(见图)。数据正在读取和处理(基于控制台窗口中的结果),但是GUI中的图形不能实时更新。它只更新,直到我停止应用程序读取和处理任何更多的数据。我知道这个问题与线程有关。我相信我在更新GUI时在同一个线程上运行数据读取和处理。下面是我进行数据抓取和处理以及GUI更新的代码:
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
vector<int> test;
test.push_back(1);
PD.setChannels(test);
//Grab and process data until the escape key is pressed
while (!GetAsyncKeyState(VK_ESCAPE)) {
PD.refreshBufferSize();
PD.grabDataFromBuffer();
vector<double> fireRates = PD.getFireRates();
//Debug code to print to console
for (int i = 0; i < fireRates.size(); i++) {
cout << fireRates[i] << endl;
}
Sleep(10); //wait 10 ms before getting the next buffer of data
//update GUI below
vector<int> channels = PD.getChannels();
for (int i = 0; i < channels.size(); i++) {
chart1->Series["Fire Rate"]->Points->AddXY(channels[i], fireRates[i]);
}
}
}我已经尝试过寻找解决方案,并找到了一些可以使用BeginInvoke、委托和调用方法的东西,但是其中大多数都是在C#中,并且很难理解。我之所以使用C++,是因为我使用了一些DLL文件来调用某些函数,这些函数帮助我获取我想要处理和分析的数据,而在我的经验中,C#在尝试使用DLL文件时非常努力。此外,我发现的关于如何在C++中使用这些方法的文档和示例并不十分清楚,或者不能很好地转换为C++。
我的问题是如何在C++/CLR中实时更新GUI图表?使用C++/CLR可以做到这一点吗?如果是这样,你能给我举个例子吗?非常感谢您的帮助!谢谢!
发布于 2016-06-30 19:57:18
您是对的-- GUI线程仅限于在while循环中执行,因为它从不离开该方法,因此它从不执行包括WM_PAINT消息在内的窗口消息处理,因此屏幕永远不会被重新绘制。
您需要将获取放在一个单独的线程上,然后将调用同步回GUI以进行更新。下面是一个例子:
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
System::Threading::ThreadPool::QueueUserWorkItem(gcnew WaitCallback(acquireData));
}
void acquireData(Object^ state)
{
vector<int> test;
test.push_back(1);
PD.setChannels(test);
//Grab and process data until the escape key is pressed
while (!GetAsyncKeyState(VK_ESCAPE)) {
PD.refreshBufferSize();
PD.grabDataFromBuffer();
vector<double> fireRates = PD.getFireRates();
//Debug code to print to console
for (int i = 0; i < fireRates.size(); i++) {
cout << fireRates[i] << endl;
}
Sleep(10); //wait 10 ms before getting the next buffer of data
//update GUI below
vector<int> channels = PD.getChannels();
for (int i = 0; i < channels.size(); i++) {
chart1->BeginInvoke(gcnew Action<int, int>(updateChart), gcnew array<Object^>(channels[i], fireRates[i]));
}
}
}
void updateChart(int channel, int fireRate)
{
chart1->Series["Fire Rate"]->Points->AddXY(channel, fireRate);
}其中一个问题是,它在一个紧循环中调用BeginInvoke。这可能会使性能受到影响(一定要测量,看看是否确实如此)。这是一个问题,因为您使用的是vector<int>,并且不能将此类型传递到任何托管方法中。您需要将数据从向量复制到.Net类型中,以便将其传递到BeginInvoke中。
https://stackoverflow.com/questions/37885788
复制相似问题