0
votes

In my WPF application I have a for loop that after a button click manipulates a Canvas control.

for (var i = 0; i < numOfIterations; i++)
{
    swarm.iterate();
    myCanvas.Children.Clear();
    for (int j = 0; j < numCities - 1; j++)
    {
        Line line = new Line();
        line.Stroke = System.Windows.Media.Brushes.Black;
        line.X1 = ScaleX(cities[swarm._gbestlist[j]].x, maxX);
        line.X2 = ScaleX(cities[swarm._gbestlist[j + 1]].x, maxX);
        line.Y1 = ScaleY(cities[swarm._gbestlist[j]].y, maxY);
        line.Y2 = ScaleY(cities[swarm._gbestlist[j + 1]].y, maxY);
        line.StrokeThickness = 2;
        myCanvas.Children.Add(line);
    }
}

As you probably know, the UI is not responsive during the execution of the loop and after the loop finished, the result after last iteration is visible. What should I do to have a "live" preview of the lines being added and deleted?

I tried using BackgroundWorker:

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    double maxX = FindMaxX();
    double maxY = FindMaxY();
    for (int i = 0; i < 250; i++)
    {
        swarm.iterate();
        RemoveLines();
        for (int j = 0; j < cities.Count - 1; j++)
        {
            Line line = new Line();
            line.Stroke = System.Windows.Media.Brushes.Black;

            line.X1 = ScaleX(cities[swarm._gbestlist[j]].x, maxX);
            line.X2 = ScaleX(cities[swarm._gbestlist[j + 1]].x, maxX);
            line.Y1 = ScaleY(cities[swarm._gbestlist[j]].y, maxY);
            line.Y2 = ScaleY(cities[swarm._gbestlist[j + 1]].y, maxY);

            line.StrokeThickness = 2;  
            myCanvas.Children.Add(line);
        }
    }
}

But I get

System.InvalidOperationException was unhandled by user code: The calling thread cannot access this object because a different thread owns it.

1
add your elements asynchronously...user3455395
Do it in other thread/task (with Invoke) or split cycle into steps and use timer to progress through them.Sinatr
I tried using BackgroundWorker. Please, see the edit. It seems like I can not modify UI elements from a different thread.pmichna

1 Answers

0
votes

You could still do it asynchronously using the application dispatcher. Also, If you split the iteration into steps using a timer as Sinatr suggested, you could get the desired effect.

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,new           
Action(DoWork)

Hope it helps.