简体   繁体   中英

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 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 . 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. 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 )

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 should only be responsible for representation, meaning it should only assign given value, not calculate it.

This is perfect use case for new await async keywords introduced in 4.5 framework version.

To achieve described behavior I would suggest using Task class as such:

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 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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