【发布时间】:2019-06-12 07:07:05
【问题描述】:
我有一个 wpf 应用程序,它有 mainWindow 创建在辅助监视器上显示的 _otherWindow。两个窗口都有需要随时间变化的元素。 (mainWindow 更新 Image 和 plots 图表,最后 _otherWindow 更新 shape 位置,具体取决于某些计算)。
我的问题是什么?好吧,我正在Thread 中逐帧阅读视频(但是我想允许使用相机拍摄的流)。当我在特定时间内每帧更新 GUI 时,应用程序的负载越来越大,而且速度越来越慢......
我意识到评论 mainWindow updating Image 或评论 _otherWindow updating shape position 代码可以使应用程序运行良好,但问题是它们一起运行时。
这里有详细的说明
首先我计算_otherWindow 内部的一些东西并计算shape 的位置。
然后我计算一些与image 和update frame 相关的东西,将一些东西添加到bitmap
然后我在_otherWindow 中更新形状的位置
最后我绘制结果(绘图需要从mainWindow 和_otherWindow 获得的数据)
为此,我使用任务并等待它们。
我有这个:
private Thread _camera;
private void CaptureVideo()
{
_camera = new Thread(CaptureVideoCallback)
{
Priority = ThreadPriority.Highest
};
_camera.Start();
}
private VideoCapture _capture;
private void CaptureVideoCallback()
{
//some computing here read from a video file...
_capture = new VideoCapture("someVideo.mp4");
for (var i = 0; i < _capture.FrameCount; i++)
{
_capture.Read(_frame);
if (_frame.Empty()) return;
//*************task that does heavy computation in other class
var heavyTaskOutput1 = Task.Factory.StartNew(() =>
{
_otherWindow.Dispatcher.Invoke(() =>
{
ResultFromHeavyComputationMethod1 = _otherWindow.HeavyComputationMethod1();
});
}
);
////*************task that does heavy computation in current class
var heavyTaskOutput2 = Task.Factory.StartNew(() =>
{
ResultFromHeavyComputationMethod2 = HeavyComputationMethod2(ref _frame);
var bitmap = getBitmapFromHeavyComputationMethod2();
bitmap.Freeze();
//update GUI in main thread
Dispatcher.CurrentDispatcher.Invoke(() => ImageSource = bitmap);
});
////*************wait both task to complete
Task.WaitAll(heavyTaskOutput1, heavyTaskOutput2 );
//update _otherWindow GUI
var outputGui = Task.Factory.StartNew(() =>
{
_otherWindow.Dispatcher.Invoke(() =>
{
_otherWindow.UpdateGui();
});
}
);
outputGui.Wait();
////*************plot in a char using gotten results, UPDATE GUI
Task.Run(() =>
{
PlotHorizontal();
});
}
}
什么是加快速度的好方法? 我的意思是我知道 GUI 的东西需要在主线程上完成,但这会减慢速度。
编辑
按照 Clemens 的建议更改了代码:
//*************task that does heavy computation in other class
var heavyTaskOutput1 = Task.Run(() =>
{
ResultFromHeavyComputationMethod1 = _otherWindow.HeavyComputationMethod1();
}
);
////*************task that does heavy computation in current class
var heavyTaskOutput2 = Task.Run(() =>
{
ResultFromHeavyComputationMethod2 = HeavyComputationMethod2(ref _frame);
var bitmap = getBitmapFromHeavyComputationMethod2();
bitmap.Freeze();
//update GUI in main thread
Dispatcher.CurrentDispatcher.Invoke(() => ImageSource = bitmap);
});
////*************wait both task to complete
Task.WaitAll(heavyTaskOutput1, heavyTaskOutput2);
//update _otherWindow GUI
var outputGui = Task.Run(() =>
{
_otherWindow.Dispatcher.Invoke(() =>
{
_otherWindow.UpdateGui();
});
}
);
outputGui.Wait();
【问题讨论】:
-
heavyTaskOutput1在它只做Dispatcher.Invoke时似乎毫无意义。也许在Invoke之前调用_otherWindow.HeavyComputationMethod1。您可能还想使用Task.Run而不是Task.Factory.StartNew。参见例如这里:stackoverflow.com/questions/38423472/… -
好的,我已经添加了建议的更改。有没有进一步改进的可能?
标签: c# wpf performance task