派生曲线计算与 UI 绘制分离(后台线程 + 双缓冲),彻底消除交互卡顿
根因:重计算发生在绘制线程内(Paint 同步算派生预览曲线),一次整段弱波增强约 368ms 会阻塞消息循环,滑块/光标/视界失去跟手。 方案:新增后台计算线程 + 双缓冲。大窗口预览曲线不在绘制线程计算,本帧用最新旧曲线顶替并排后台任务;小窗口仍同步以保证预览实时;后台算完通过自定义消息通知宿主重绘(双缓冲切换)。条目用 shared_ptr 共享、绘制线程钉住整帧有效,后台只追加不改写,无数据竞争。任何改变数据层结构的操作前先 PauseDerivedAsync(join 后台线程),杜绝读取已释放/已移动采样。 实测 VERY_BIG_DATA(5 网格):弱波增强平移 2247ms→15ms,拖滑块 2303ms→15ms,静止重绘→0.25ms,交互均 ≤约 30ms,无 300ms/2s 级尖峰。小窗口同步路径与旧实现逐像素 0 差异。
This commit is contained in:
1 parent
aca84df0ac
commit
99247622c1
4 files changed
+520
-167
No files matched your search
@@ -583,6 +583,8 @@ namespace jdi
|
||||
}
|
||||
const std::wstring name = file->fileName;
|
||||
|
||||
// 移除文件会释放大量采样内存:先暂停后台派生曲线计算,避免其读取已释放内存。
|
||||
m_plot.PauseDerivedAsync();
|
||||
// 先按旧下标修正各标签页配置与共享选中项,再从数据层移除,最后统一对齐。
|
||||
for (TabConfig& tab : m_tabs)
|
||||
{
|
||||
@@ -617,6 +619,8 @@ namespace jdi
|
||||
return;
|
||||
}
|
||||
|
||||
// 移除信号会释放采样内存:先暂停后台派生曲线计算,避免其读取已释放内存。
|
||||
m_plot.PauseDerivedAsync();
|
||||
// 先按旧下标修正各标签页配置与共享选中项,再从数据层移除(释放采样内存),最后对齐。
|
||||
for (TabConfig& tab : m_tabs)
|
||||
{
|
||||
@@ -937,6 +941,9 @@ namespace jdi
|
||||
}
|
||||
|
||||
int fileIndex = -1;
|
||||
// 插入新文件会移动 DataFile/SignalData 的存储位置,必须先暂停后台派生曲线计算,
|
||||
// 否则后台线程可能正在读取即将被移动的采样数据。
|
||||
m_plot.PauseDerivedAsync();
|
||||
// 此处只做一次指针/缓冲移动,不拷贝任何采样数据,因此不会造成可见卡顿。
|
||||
if (!m_dataSet.AddDataFile(std::move(file), fileIndex))
|
||||
{
|
||||
@@ -1498,6 +1505,8 @@ namespace jdi
|
||||
|
||||
// 3. 插入到原信号的下方(数据层 + 各标签页引用重映射)。
|
||||
int newIndex = -1;
|
||||
// 插入派生信号会移动该文件的信号存储:先暂停后台计算,避免其读取已移动的数据。
|
||||
m_plot.PauseDerivedAsync();
|
||||
if (!m_dataSet.InsertDerivedSignal(request.fileIndex, request.signalIndex, std::move(derived),
|
||||
newIndex))
|
||||
{
|
||||
@@ -1919,7 +1928,7 @@ namespace jdi
|
||||
// WM_PAINT / WM_TIMER 的重绘范围由各自的处理分支判断,这里不做标记。
|
||||
if (message != WM_PAINT && message != WM_MOUSEMOVE && message != WM_MOUSELEAVE &&
|
||||
message != WM_SETCURSOR && message != WM_NCHITTEST && message != WM_TIMER &&
|
||||
message != WM_ERASEBKGND)
|
||||
message != WM_ERASEBKGND && message != kMessagePlotDerivedReady)
|
||||
{
|
||||
m_chromeDirty = true;
|
||||
}
|
||||
@@ -2145,6 +2154,10 @@ namespace jdi
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case kMessagePlotDerivedReady:
|
||||
// 后台派生曲线计算完成:只失效绘图区,下一帧即可取到最新曲线(双缓冲切换)。
|
||||
InvalidatePlotRect(hwnd, m_plotRect);
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
{
|
||||
ReleaseBackBuffer();
|
||||
|
||||
Reference in new issue
Block a user