Как определить, что элемент управления признан недействительным?

#c# #winforms #invalidation

#c# #winforms #недействительность

Вопрос:

Я решаю проблему производителя / потребителя. код выглядит следующим образом:

 void producer()
{
  // produce item
  // update some control in form
}

void consumer()
{
  // consume item
  // update some control in form
}
  

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

 void producer()
{
  // produce item
  // put the work to be done in a queue
  this.Invalidate();
}

void consumer()
{
  // consume item
  // put the work to be done in a queue
  this.Invalidate();
}
  

Итак, теперь я должен определить, была ли форма признана недействительной. Я посмотрел в списке событий формы, и лучшее, что я смог найти, было событие рисования. Я ввел код, который выполнил задание, и он работает нормально. Проблема в том, что я почему-то сомневаюсь, что сделал это правильно, хотя это работает. Я думаю, что paint — неподходящее место для выполнения этой работы, поскольку то, что я делаю, это не просто рисование. Мне было интересно, есть ли лучший способ сделать это.

Редактировать — Фрагмент для недействительного обработчика событий не работает

 public Form1()
{
  InitializeComponent();
  this.Invalidated  = InvalidateEventHandler;
}
void producer(object o)
{
  // produce
  // put work in queue
  this.Invalidate();
}
public void InvalidateEventHandler(object sender, InvalidateEventArgs e)
{
  // Do Stuff to form -- Where exception raises
}
  

Ответ №1:

Функция Invalidate предназначена для запуска Paint.

Что вам нужно, так это Control.Invoke() ваш собственный метод обновления формы.

Редактировать:

Ваши потоки, отличные от GUI, не должны даже вызывать Invalidate(), они не могут касаться GUI.

Вы можете написать свой собственный метод ProcessData() form- и из вызова Prod / Cons mainForm.Invoke(ProcessData)

Then ProcessData() отвечает за потокобезопасный доступ к данным и за аннулирование GUI

Комментарии:

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

Ответ №2:

Вы можете попробовать использовать new ключевое слово, чтобы создать свою собственную реализацию Invalidate

     public new void Invalidate()
    {
        // place your logic here
        base.Invalidate();
    }
  

Также форма признала недействительным событие, которое запускается после завершения Ivalidate

Редактировать:

 public void InvalidateEventHandler(object sender, InvalidateEventArgs e)
{
    anotherForm.Invoke(new Action(() =>
    {
        // Do Stuff to form -- Where exception raises
    }));
}
  

Комментарии:

1. @Stecya АХ! да, у него есть событие недействительности, но оно не отображается в окне свойств, idk почему, я попробовал это в коде, и это было показано. Но что касается использования моей собственной реализации Invalidate(), нет, это не сработает, потому что я вызываю Invalidate с потоком, отличным от того, который создал мою форму, так что это был бы тот, который выполняет Invalidate, и у меня была бы та же проблема.

2. Тогда использование event — это ваше решение

3. К сожалению, это не работает, я не знаю почему. Я добавил новый обработчик события в недействительное событие, и когда оно выполняется, я получаю ту же ошибку о том, что оно обновляется из другого потока, отличного от того, который создал форму. 🙁

4. Вы должны использовать Invoke для взаимодействия с другой формой из другого потока. Смотрите мою правку