0

I have some trouble with updating of Canvas`s content using Parallel.Foreach or IEnumerable.AsParallel().ForAll() or Threads.

I have a lot of Lines in Canvas, and i need to change their coordinates relatievly to the new size of Canvas in which they are, when user resizes the window.

I Put my Lines in

    IEnumerable<Line> lineCollection = canvas.Children.OfType<Line>();

Then i trying to loop them parallel using Parallel.Foreach or IEnumerable.AsParallel().ForAll()

I recieve an AggregateException in that cases. It says, that the calling thread cannot access this object because the main thread owns it.

How can I do that with my UIElements.

This is my code:

    private void canvas_SizeChanged(object sender, SizeChangedEventArgs e)
    {

        Double hDelta = e.NewSize.Height / e.PreviousSize.Height;

        if (Double.IsInfinity(hDelta)) return;

        IEnumerable<Line> LineCollection = canvas.Children.OfType<Line>();
        try
        {
            Parallel.ForEach(LineCollection, (line) =>
            {
                Double topProp = (Double)line.GetValue(Canvas.TopProperty) * hDelta;

                line.SetValue(Canvas.TopProperty, topProp);
            });
        }
        catch (AggregateException ae)
        {
            ae.Handle((x) =>
            {
                if (x is Exception)
                {
                    MessageBox.Show(x.ToString(), "error");
                }
                return false;
            });
        }
    }

I recieve an Error at this line:

line.SetValue(Canvas.TopProperty, topProp);

1 Answers1

0

This is solved my problem.

        Line[] keysLineCollection = YAxisKeys.Children.OfType<Line>().ToArray();
        Label[] keysLabelCollection = YAxisKeys.Children.OfType<Label>().ToArray();
        try
        {
            new Thread(delegate ()
            {
                Parallel.ForEach(keysLineCollection, (line, loopstate, elementIndex) =>
                {

                    /*keysLineCollection[elementIndex]*/
                    line.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        Double topProp = ((Double)line.GetValue(Canvas.TopProperty) - 11.0) * hDelta + 11.0;
                        switch (topProp - 11.0 < 0)
                        {
                            case true:
                                line.Visibility = Visibility.Hidden;
                                break;
                            default:
                                line.Visibility = Visibility.Visible;
                                break;
                        }
                        line.SetValue(Canvas.TopProperty, topProp);
                    }));
                    keysLineCollection[elementIndex] = line;
                });
            }).Start();

            new Thread(delegate ()
            {
                Parallel.ForEach(keysLabelCollection, (label, loopstate, elementIndex) =>
                {

                    /*keysLabelCollection[elementIndex]*/
                    label.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        Double topProp = (Double)label.GetValue(Canvas.TopProperty) * hDelta;
                        switch (topProp < 0)
                        {
                            case true:
                                label.Visibility = Visibility.Hidden;
                                break;
                            default:
                                label.Visibility = Visibility.Visible;
                                break;
                        }
                        label.SetValue(Canvas.TopProperty, topProp);
                    }));
                    keysLabelCollection[elementIndex] = label;
                });
            }).Start();
        }
        catch (AggregateException ae)
        {
            ae.Handle((x) =>
            {
                if (x is Exception)
                {
                    MessageBox.Show(x.ToString(), "error");
                }
                return false;
            });
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.ToString(), "error");
        }

I used

Line[] keysLineCollection = YAxisKeys.Children.OfType<Line>().ToArray();

instead of

IEnumerable<Line> lineCollection = canvas.Children.OfType<Line>();

and applied Dispatcher to elements in arrays.

It works great for me.