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

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

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

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

Изменить - Фрагмент для обработчика событий Invalidated не работает

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
}

person atoMerz    schedule 14.05.2011    source источник


Ответы (2)


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

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

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

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

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

Затем ProcessData() отвечает за потокобезопасный доступ к данным и за недействительность графического интерфейса.

person Henk Holterman    schedule 14.05.2011
comment
Может быть, я не понимаю, но как это решает мою проблему с выполнением потока, который не является создателем? Могли бы вы объяснить? - person atoMerz; 14.05.2011

Вы можете попробовать использовать ключевое слово 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
    }));
}
person Stecya    schedule 14.05.2011
comment
@Стеция АРХ! да, у него есть событие Invalidated, но оно не отображается в окне свойств, не знаю почему, я попробовал его в коде, и оно было показано. Но что касается использования моей собственной реализации Invalidate(), нет, это не сработает, потому что я вызываю Invalidate с потоком, отличным от того, который создал мою форму, поэтому это будет тот, который выполняет Invalidate, и у меня будет та же проблема. - person atoMerz; 14.05.2011
comment
Тогда использование события - ваше решение - person Stecya; 14.05.2011
comment
К сожалению, он не работает, я не знаю, почему. Я добавил новый обработчик событий в событие Invalidated, и когда он выполняется, я получаю ту же ошибку о том, что он обновляется из другого потока, отличного от того, который создал форму. :( - person atoMerz; 14.05.2011
comment
Вы должны использовать Invoke для взаимодействия с другой формой из другого потока. Смотрите мое редактирование - person Stecya; 14.05.2011