[英]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.