Запуск метода Clear() для BindingList‹Object› вызывает исключение перекрестного потока

Я использую Bindinglist<Object> и DataGridView для заполнения списка объектов и отображения его в DataGridView.

Мой список заполняется другим потоком, а не потоком DataGridView, поэтому я использую метод Invoke в методе ListChanged(), который я написал в потоке графического интерфейса (поток, в котором находится DataGridView).

Теперь, пока я добавляю Object в BindingList в основном потоке (который обрабатывает список) - DataGridView был обновлен Хорошо, НО, когда я пытаюсь запустить метод Clear() в BindingList - мой метод ListChanged() запускается, но я все еще получаю исключение: Cross-thread operation not valid: Control 'dgv' accessed from a thread other than the thread it was created on. Почему я получаю это исключение? Я лечу GUI уже в методе ListChanged(), Нет?

Код:

myBindingList.ListChanged += new ListChangedEventHandler(Events_ListChanged);
BindingSource source = new BindingSource(myBindingList, null);
dgv.DataSource = source;

Запустите метод Clear() в основном потоке:

myBindingList.Clear();

мой метод ListChanged():

void Events_ListChanged(object sender, ListChangedEventArgs e)
{
     if (dgv.InvokeRequired)
     {
         dgv.Invoke(new UpdateDataGridItemDelegate(this.Events_ListChanged), sender, e);
         return;
     }
     else
     {
         source.ResetBindings(false);
         lblTotal.Text = myBindingList.Count.ToString();
     }
}

И я подчеркиваю: когда я добавляю объекты в список привязки, он работает хорошо, и я не получаю исключения (я делаю это из того же потока, что и запускаю метод Clear()), но когда я запускаю метод Clear() это бросает мне исключение "Cross Thread". Любая идея Почему?


person user3820978    schedule 15.07.2014    source источник
comment
Элемент управления 'dgv' доступен из потока, отличного от потока, в котором он был создан. Я не вижу ничего с именем dgv ни в одном из предоставленных вами кодов. Это фактический код или приблизительный?   -  person spender    schedule 15.07.2014
comment
Это вполне допустимое исключение. Ваш вызов Clear() выполняется из рабочего потока, поэтому привязка обновляется в рабочем потоке, поэтому элемент управления обновляется в рабочем потоке. Это незаконно и приведет к тому, что ваша программа не сможет диагностироваться.   -  person Hans Passant    schedule 15.07.2014
comment
Вот что я сказал: я обновляю GUI из потока GUI методом Invoke()   -  person user3820978    schedule 15.07.2014
comment
транжира, я обновил код.   -  person user3820978    schedule 15.07.2014


Ответы (1)


Я изменил свой метод ListChanged() следующим образом, и он работает!:

void Events_ListChanged(object sender, ListChangedEventArgs e)
{
     if (dgv.InvokeRequired)
     {
         dgv.Invoke(new UpdateDataGridItemDelegate(this.Events_ListChanged), sender, e);
         return;
     }
     else
     {
         if (e.ListChangedType == ListChangedType.Reset)
         {
             dgv.DataSource = null;
             source = new BindingSource(myBindingList, null);
             dgv.DataSource = source;
         }
         else
             source.ResetBindings(false);
         lblTotal.Text = myBindingList.Count.ToString();
     }
}

Я отвязал источник данных DataGridView и снова привязал его к BindingList в случае сброса BindingList.

person user3820978    schedule 16.07.2014
comment
Как выглядит ваш делегат? У меня точно такая же проблема, как и у вас. Попытка добавить/очистить элементы в BindingList, привязанном к моему источнику DataGridView из другого потока. - person HiTech; 19.02.2015