简体   繁体   English

WPF:通过绑定更新折线的Points属性会导致滞后

[英]WPF: Updating Polyline's Points property via binding causes lag

I have a custom graph control that uses a Polyline object to render waveforms. 我有一个自定义图形控件,该控件使用Polyline对象渲染波形。

<Polyline Name="Line" Points="{Binding LinePoints}"
    Stroke="{Binding LineColor}"
    StrokeThickness="{Binding LineThickness}">

In my ViewModel, I will generate different sets of "LinePoints" every short while (50-200ms) via a DispatcherTimer . 在我的ViewModel中,每隔一小段时间(50-200毫秒),我就会通过DispatcherTimer生成不同的“ LinePoints”集。 The binding works perfectly fine, I am getting animated waveform at the View, except that it is causing significant lag in the user interface. 绑定工作得非常好,我在视图上获得了动画波形,除了它在用户界面中造成了明显的滞后。 For example, when I right click on something else in the Window, the context menu would appear with very very laggy animation. 例如,当我右键单击“窗口”中的其他内容时,上下文菜单将出现非常滞后的动画。

Of course, I could change the timer to tick every 500ms, and the lag would be significantly reduced. 当然,我可以将计时器更改为每500ms滴答一次,这样可以大大减少延迟。 But, this would make my graph looks sloppy. 但是,这会使我的图形显得草率。 Is there any methods I can do to shift some of these to another thread? 我有什么方法可以将其中一些转移到另一个线程?

(Side note: The generation of LinePoints is not the main cause of the lag. Each generation is using about 1ms of execution time. This value is obtained from System.Diagnostics.Stopwatch ) LinePoints说明: LinePoints的生成不是滞后的主要原因。每一代都使用大约1毫秒的执行时间。该值从System.Diagnostics.Stopwatch获得)

So since the operation of calculating all the required points are heavy on UI you should use additional Thread to cover the calculation. 因此,由于计算所有必需点的操作在UI上很繁琐,因此您应该使用其他Thread来进行计算。 UI Thread should only be responsible for representation, meaning it should only assign given value, not calculate it. UI Thread应仅负责表示形式,这意味着它应仅分配给定值,而不计算值。

This is perfect use case for new await async keywords introduced in 4.5 framework version. 这是4.5框架版本中引入的新的await async keywords理想用例。

To achieve described behavior I would suggest using Task class as such: 为了实现描述的行为,我建议像这样使用Task class

private async void InvokeHandler()
{
   while(true)
   {
       // Passes variable to calculation method and waits for result without blocking.
       ViewModel.Points = await Task.Run(() => CalculatePoints(new object()));
       await Task.Delay(100);
   }
}
private Task<PointCollection> CalculatePoints(object requiredArguments)
{
    var points = new PointCollection();
    // Do calculations here with requiredArgument passed from a caller.
    return Task.FromResult(points);
}

How does it work? 它是如何工作的? In InvokeHandler method you start up a Task which could essentially be another Thread (gathered from ThreadPool if current Thread does not have enough resourceses to run provided Delegate ), which will not block your currently running Thread and after it finished executing it will return you a result ( PointCollection ). InvokeHandler方法中,您将启动一个Task ,该Task本质上可能是另一个Thread (如果当前Thread没有足够的资源来运行提供的Delegate ,则从ThreadPool收集),它将不会阻塞您当前正在运行的Thread并且在执行完之后将返回一个结果( PointCollection )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM