2010-01-29 3 views
11

Я работаю с фреймворком, который запускает собственный диспетчер событий в отдельном потоке. Структура может генерировать некоторые события.Обработка событий в C#

class SomeDataSource { 

    public event OnFrameworkEvent; 

    void FrameworkCallback() { 

     // This function runs on framework's thread. 

     if (OnFrameworkEvent != null) 
      OnFrameworkEvent(args); 
    } 
} 

Я хочу доставить эти события к объекту Winforms в потоке Winforms. Я, очевидно, проверяю InvokeRequired и при необходимости отправлю его в Winforms.

class SomeForm : Form { 

    // ... 

    public void SomeAction(SomeArgs args) { 
     if (InvokeRequired) { 
      BeginInvoke(new Action(SomeAction), args); 
      return; 
     } 

     // ... 
    } 

} 

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

var form = new SomeForm(); 
var src = new SomeDataSource(); 

// ... 

src.OnFrameworkEvent += form.SomeAction; 
form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction; 
  1. В настоящее время этот подход нить-сейф? Если форма находится в процессе закрытия, а внешний поток вызывает BeginInvoke, будет ли вызов выполняться в очереди, если форма закрыта? (что означает, что у меня все еще есть возможность столкнуться с одной и той же проблемой)

  2. Есть ли лучший подход или рекомендуемый образец для обработки событий с перекрестными потоками?

ответ

4

Нет это не так. Поток может просто выполнять обработчик события, когда вы его отмените и закроете. Небольшие шансы, но не ноль. Перед тем, как закрыть форму, необходимо остановить поток. Если вы не хотите прервать его, вам нужно оставить форму открытой, отменив событие FormClosing, а затем позвольте обратному завершению завершения потока закрыть форму.

Проверьте, пожалуйста, this thread.

+0

Мне нравится этот подход. Мне нравится использовать методы обратного вызова для сигнализации, когда поток выполняется. –

1

Я не использовал фреймворк со своим диспетчером событий, но у меня был собственный опыт с потоками, которые я создал. Вот мой опыт

  1. Этот подход не является потокобезопасным. Вызов будет вызываться, даже если сама программа закрыта. Я видел это в диспетчере задач (после того, как программа закрыта, как вы говорите), как висящие потоки. (даже если вы также запустите программу из диспетчера задач). Я должен был убить эти потоки отдельно позже.

  2. Когда форма закрывается, вы должны убить поток диспетчера, чтобы он не зависал, если что-то не так происходит в этой теме.

    form.Closing += (sender, eargs) => src.OnFrameworkEvent -= form.SomeAction; 
    // pseudo-code (find c# equivalent) 
    if (dispatcherthread.isrunning) 
    dispatcherThread.kill(); 
    
+0

Что делать, если поток диспетчера должен оставаться живым для обработки других Winforms? –

+0

Я боюсь, что это так. У меня есть несколько форм, которые слушают один и тот же источник событий. –

+0

Если я правильно понимаю, что вы говорите, то установление свойства IsBackground потока в true предотвратит зависание потоков. –

2

Вы можете добавить этот код в конструктор CheckForIllegalCrossThreadCalls = false;, и никакие исключения не будут выбрасываться.

Смежные вопросы