有一种情况--我在C#上做了一些数学建模应用程序,以实时矢量图形的形式展示了它的结果。数学做得很好(迭代过程,每帧绘制),但有一个问题-当我使用额外的线程进行计算时,绘制结果应该使用Dispatcher.BeginInvoke (每帧!)这是一个相当昂贵的操作(分析显示,它几乎占用了30%的时间)。但是,如果我尝试在UI线程中执行所有操作,我将只看到最后一帧(正如预期的那样)。
计算和显示结果是app唯一的任务,所以我甚至不需要GUI在建模期间响应-但我需要实时显示结果……
所以我想避免BeginInvoke,同时显示结果,但我看不到一种方法。你知道怎么安排这样的计算吗?图形显示在DrawingVisual中的某个空FrameworkElement中。
Thx
发布于 2010-03-03 22:19:50
事件选项1:呈现事件
在单独的线程上执行计算,但将对UI的更改排入队列,并在渲染事件中更新它们。它看起来像这样:
PresentationSource.FromVisual(window).CompositionTarget.Rendering += (obj, e) =>
{
foreach(var update in _queue)
UpdateUI(update);
}
这段代码假设_ queue 's是线程安全(同步)队列。您可以创建这样一个队列类,也可以下载一个。或者,您可以用"lock(_queue)“将"foreach”括起来。
这比Dispatcher.BeginInvoke()更好的原因是: 1.它是在每一帧之前调用的,所以如果帧速率下降,它被调用的频率就会降低;2.它会分批处理更改。
选项2:多UI线程
您可以使用单独的hWnd在单独的线程上运行UI的一部分。为此,您可以使用WindowsFormsIntegration或使用一些Win32魔术。这里有一种方法:
在新线程中,构造窗口并显示它(不要忘记Appliation.Run())
动画选项3:
您可以创建自己的自定义动画派生类来设置UI项的动画效果。这些可以使用从模型中预测的数据。这样做的好处是精确的时间同步:每次调用你的代码时,它都确切地知道“何时”(在动画时间中),它正在计算的位置。因此,如果某个其他程序占用CPU或GPU一秒钟,并且速度和帧速率变慢,动画仍会以较低的帧速率平滑地进行。
为此,将DoubleAnimationBase
子类化并覆盖GetCurrentValueCore()以执行自定义计算,并结合所需的Clone()和CreateInstanceCore()覆盖。然后使用此选项来设置属性的动画。
如果仅为现有对象的双重属性设置动画效果还不够,则可以创建一个动画来生成整个对象,如几何体、Geometry3D、绘图、Drawing3D甚至UIElement。为此,将AnimationTimeline子类化并覆盖GetCurrentValue()和其他方法。
使用动画的优点与使用呈现事件相同,只是您可以让WPF为您处理所有时钟同步和重播速度问题,而不是自己处理。如果只能为正在更改的属性设置动画,也可能会导致代码减少。
发布于 2010-03-03 18:02:25
在每次迭代过程结束时,您可以在需要重新绘制的可视对象上手动调用InvalidateVisual()方法,这将发送一条绘制消息来重新绘制控件/窗口。
发布于 2010-03-03 20:51:33
使用DataBinding,让我们使用该机制来考虑如何通过ObservableCollection刷新UI。祝好运
https://stackoverflow.com/questions/2370135
复制相似问题