dif
dif

Reputation: 2493

WPF: Animated Line slows down UI

I'm drawing a line in my UI that needs to be updated everytime the graphics are redrawn. Since I'd like my UI still to be responsive (which is it not, at the moment), I'm using a backgroundworker that gets called everytime the UI is rendered. As mentioned, at the moment the UI becomes unresponsive and slow when the line is drawn. Is there anything I could change to improve my software?

This is the code I'm using (at least the parts that are relevant).

BackgroundWorker _worker = new BackgroundWorker();
_worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);

void CompositionTarget_Rendering(object sender, EventArgs e)
{
    if (!_worker.IsBusy) { _worker.RunWorkerAsync(); }
}

The Line I'm using is generated out of an array of Point[]. To make sure nothing else is slowing the software down, I stripped the line generation down to just using dummy-values:

void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    Dispatcher.BeginInvoke((Action)delegate
    {
        Point[] line = new Point[480];

        MySegment1.Points.Clear();
        bool isStart = true;

        for (int i = 0; i < line.Length; i++)
        {
            line[i] = new Point(0, 0);
            if (isStart)
            {
                MyFigure1.StartPoint = line[i];
                isStart = false;
            }
            else
                MySegment1.Points.Add(new Point(i, line[i].Y + 10));
        }
    });
}

The XAML for the line looks like this:

<Path Stroke="GreenYellow" StrokeThickness="2" Name="MyPath1"  Grid.Column="1">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure x:Name="MyFigure1" StartPoint="0,0">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <PolyBezierSegment x:Name="MySegment1"/>
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>

Thanks a lot for any recommandations!

EDIT: In addition to Clemens answer I also changed the DispatcherPriority to System.Windows.Threading.DispatcherPriority.ApplicationIdle, which also increased the responsibility of the UI a lot. I think this is a state I can live with at the moment... :)

Upvotes: 1

Views: 251

Answers (1)

Clemens
Clemens

Reputation: 128060

There would be no need for all this BackgroundWorker "optimization" if you did not update the PolyBezierSegment point by point, but instead create a new PointCollection and assign it to the Points property of the PolyBezierSegment:

private Random random = new Random(); // creates some sample data

private void CompositionTarget_Rendering(object sender, EventArgs e)
{
    var line = new Point[480];

    for (int i = 0; i < line.Length; i++ )
    {
        line[i] = new Point(i, random.Next(0, 100));
    }

    MyFigure1.StartPoint = line[0];
    MySegment1.Points = new PointCollection(line); // here
}

Please note also that WPF provides more efficient ways of rendering graphics than a PathGeometry in a Path control. You may start reading the Graphics and Multimedia article on MSDN.

Upvotes: 4

Related Questions