#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 для взаимодействия с другой формой из другого потока. Смотрите мою правку