gpt4 book ai didi

c# - 线程实践。建模应用

转载 作者:太空宇宙 更新时间:2023-11-03 14:32:08 25 4
gpt4 key购买 nike

情况是这样的——我在 C#(WPF) 上制作了一些数学建模应用程序,以实时矢量图形显示它的结果。数学做得很好(迭代过程,每帧绘图),但存在问题 - 当我使用额外的线程进行计算时,绘制结果应该使用 Dispatcher.BeginInvoke(每一帧!)这是一个非常昂贵的操作(分析表明它花费了将近 30% 的时间)。但是,如果我尝试在 UI 线程中完成所有操作,我只会看到最后一帧(正如预期的那样)。

计算和显示结果是应用程序的唯一任务,所以在建模期间我什至不需要 GUI 来响应 - 但我需要实时显示结果...

所以我想避免 BeginInvoke 并同时显示结果,但我没有找到办法。任何想法如何以这种方式安排计算?图形显示在一些空的 FrameworkElement 中的 DrawingVisual 中。

谢谢

最佳答案

选项 1:渲染事件

在单独的线程上进行计算,但将更改排队到 UI 并在渲染事件上更新它们。它看起来像这样:

PresentationSource.FromVisual(window).CompositionTarget.Rendering += (obj, e) =>
{
foreach(var update in _queue)
UpdateUI(update);
}

此代码假定 _queue 是一个线程安全(同步)队列。您可以创建这样的队列类或下载一个。或者,您可以用“lock(_queue)”包围“foreach”。

这比 Dispatcher.BeginInvoke() 更好的原因是:1. 它在每帧之前调用,因此如果帧速率下降,它被调用的频率较低,以及 2. 它分批处理更改。

选项 2:多个 UI 线程

您可以使用单独的 hWnd 在单独的线程上运行一部分 UI。您可以为此使用 WindowsFormsIntegration 或使用一些 Win32 魔法。这是一种方法:

  1. 在新线程中,构造窗口并显示它(不要忘记 Appliation.Run())
  2. 显示新窗口后,使用 ((HwndSource)PresentationSource.FromVisual(window)).Handle 获取 hWnd
  3. 使用 Monitor 或 ManualResetEvent 将 hWnd 传回主 UI 线程
  4. 使用 WindowsFormsHost 为 hWnd 构造一个容器并将其添加到您的 UI
  5. 处理主 UI 中的调整大小事件,将它们向下传递到包含的窗口

选项 3:动画

您可以创建自己的自定义动画派生类来为您的 UI 项目设置动画。这些可以使用从模型中预先计算的数据。这样做的好处是精确的时间同步:每次调用您的代码时,它都确切地知道“何时”(在动画时间中)计算位置。因此,如果其他一些程序占用了 CPU 或 GPU 一秒钟并减慢了帧速率,动画仍会以较低的帧速率平稳进行。

为此,继承 DoubleAnimationBase 并覆盖 GetCurrentValueCore() 以执行您的自定义计算,并结合所需的 Clone() 和 CreateInstanceCore() 覆盖。然后使用它为您的属性设置动画。

如果简单地为现有对象的 Double 属性设置动画是不够的,可以创建一个动画来生成整个对象,例如 Geometry、Geometry3D、Drawing、Drawing3D 甚至 UIElement。为此,子类化 AnimationTimeline 并与其他方法一起覆盖 GetCurrentValue()。

使用动画的优势与渲染事件相同,除了您可以让 WPF 为您处理所有时钟同步和重播速度问题,而不是您自己处理。如果您可以只为正在更改的属性设置动画,还可能会减少代码量。

关于c# - 线程实践。建模应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2370135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com