2016-01-14 4 views
1

Неверное управление кросс-потоком: элемент управления '' доступен из потока , кроме потока, на котором он был создан.Непоследовательное исключение «Непрерывная операция по перекрестным потокам»

Мой коллега получает это исключение в моем коде, но я не знаю.

В форме у меня есть элемент управления, в котором пользователь может добавить некоторые строки в ListView.

Ive выставил свойство в моем элементе управления, которое возвращает строки внутри XmlDocument.

public XmlDocument XmlConfig 
{ 
    get 
    { 
     return GetXML(); 
    } 
} 

Получить XML просто берет коллекцию ListViewItem и форматирует ее в XML-документ.

private XmlDocument GetXML() 
{ 
    foreach(ListViewItem lvi in myListView.Items) <-- Exception Here 
    { 
     // Do Stuff 
    } 
} 
  1. Почему я получаю это когда просто пытается прочитать представление списка? Я думал, что исключения кросс-потоков были, когда вы пытались обновить элемент управления из отдельного потока.

  2. Почему я тоже не получаю это исключение?

ответ

4

Я думал крест исключения нити было, когда вы пытаетесь обновить управление с помощью отдельного потока

Неверно. исключения перекрестных потоков возникают, когда элемент управления имеет доступ к не из основного потока пользовательского интерфейса. Решение тривиально, проверьте InvokeRequired и используйте Invoke.

Что касается того, почему ваш друг попадает на это, а вы нет, невозможно сказать из кода, который вы опубликовали. Возможно, он компилируется в другую целевую версию .Net, или это может быть гоночное состояние, в результате которого сокет солома вашего оборудования (например, у него больше ядер). Дело в том, что это не имеет значения. Ваш код должен быть потокобезопасным, поскольку, по-видимому, GetXML может и -, вызываемый из неинтерфейса. Вполне возможно, что ответственность за проверку для InvokeRequired должна быть на вызывающем, а не на методе. Опять же, невозможно сказать из кода.

2

При доступе к Control в другом, чем UI нить (InvokeRequired возвращает true), вы должны использовать Invoke insetead прямого вызова; чтобы не дублировать код (для UI потока и для других потоков) будет использовать метод расширения:

private XmlDocument GetXML() { 
    myListView.InvokeSynchronized(() => { 
     foreach(ListViewItem lvi in myListView.Items) { 
     // Do Stuff 
     } 
    }); 
    } 

    ... 

    public static class ControlAsyncExtensions { 
    public static void InvokeSynchronized(this Control control, Action action) { 
     if (Object.ReferenceEquals(null, action)) 
     throw new ArgumentNullException("action"); 

     if (Object.ReferenceEquals(null, control)) 
     action(); 
     else if (control.InvokeRequired) 
     control.Invoke(action); 
     else 
     action(); 
    } 
    } 
0

Я думал, что исключения кросс-потоков были, когда вы пытались обновить элемент управления из отдельного потока.

Неправильное использование. Помните, что большинство элементов управления WinForms - это обертки вокруг общих элементов управления Windows.И средства управления Windows используют сообщения как для , получая, так и для обновления, обычно через SendMessage function. Поэтому в целом, хотя звонки могут быть безопасными для выполнения из другого потока, по соображениям безопасности в реализациях управления используется каждый элемент get/set или метод вызова.

Почему я тоже не получаю это исключение?

Не имеет значения, вы не должны этого делать в первую очередь.

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