2015-10-23 3 views
0

У меня есть некоторые проблемы с обновлением содержимого Canvas с использованием Parallel.Foreach или IEnumerable.AsParallel(). ForAll() или Threads.Обновление WPF UIElements с использованием Parallel.Foreach или Threads

У меня есть много линий в холсте, и мне нужно изменить их координаты относительно нового размера холста, в котором они находятся, когда пользователь изменяет размер окна.

Я кладу линии в

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

Тогда я пытаюсь Переберите их параллельно с использованием Parallel.ForEach или IEnumerable.AsParallel(). ForAll()

Я получаю в AggregateException в том случаи. В нем говорится, что вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит его основной поток.

Как я могу это сделать с помощью своих UIElements.

Это мой код:

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; 
      }); 
     } 
    } 

Я получаю ошибку на этой линии:

line.SetValue(Canvas.TopProperty, topProp); 
+1

Вы не можете. Только основной поток может получить доступ к объекту пользовательского интерфейса. – Paparazzi

+0

Возможно, это ответит на ваш вопрос и даст вам решение: http://stackoverflow.com/questions/9980053/dispatcher-dispatch-on-the-ui-thread –

+0

Сколько строк вы на самом деле рисуете? Ваш подход кажется излишним. – Clemens

ответ

0

Это решить мою проблему.

 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"); 
     } 

Я использовал

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

вместо

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

и прикладной диспетчеру элементов в массивах.

Это отлично работает для меня.

Смежные вопросы