1

Есть Класс с циклом в отдельном потоке. Есть EventHandler и подписка на него в другом классе. Как из цикла в другом потоке безопасно создать событие? При попытке создать его и к примеру создать запись в текстбоксе само собой вылетает исключение с сообщением попытки доступа из другого потока.

Выдержки из кода:

  1. public event EventHandler<NewDataEventArgs> NewData; - объявление события
  2. NewData(this, e); - вызов события в потоке
Kromster
  • 13,809
  • 7
    http://ru.stackoverflow.com/questions/418461/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B0%D0%BC%D0%B8-%D0%B8%D0%B7-%D1%84%D0%BE%D0%BD%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE-%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B0 – 4per Aug 26 '16 at 05:47

1 Answers1

1

Так как обработчик события вызывается в том потоке, в котором было вызвано событие, у Вас получается ситуация, что Вы пытаетесь получить доступ к элементу управления из другого потока (отличного от UI) - а делать этого нельзя.

Для того что бы это "обойти" есть несколько вариантов, приведу некоторые из них:

1 Вариант

Можно воспользоваться SynchronizationContext

1) Получаем SynchronizationContext, важно получить его именно для UI поэтому где-нибудь в CodeBehind формы пишем:

_context = SynchronizationContext.Current;

2) Далее в Вашем обработчике события, который срабатывает при NewData(this, e); необходимо использовать полученный контекст синхронизации, для того что бы безопасно доступиться к UI элементу

_context?.Post(s =>
{
   // Здесь пишите код, который получает доступ к контролу
}, null);

2 Вариант

В обработчике события, который срабатывает при NewData(this, e); можно обратиться к вашему элементу управления и вызвать метод Invoke в случае WinForms

myControl.Invoke(myDelegate);

либо использовать Dispatcher.BeginInvoke в случае WPF

 Dispatcher.BeginInvoke(DispatcherPriority.Normal,
            (ThreadStart)delegate()
        {
            // Здесь пишите код, который получает доступ к контролу
        }
sp7
  • 5,269