Я работаю с платформой, которая выполняет ее собственного диспетчера события в отдельном потоке. Платформа может генерировать некоторые события.
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;
Теперь, действительно ли этот подход ориентирован на многопотоковое исполнение? Если форма находится в процессе того, чтобы быть закрытым, и внешний поток звонит BeginInvoke
, вызов будет все еще поставлен в очередь для выполнения, если форма будет закрыта? (что означает, что у меня все еще есть шанс обнаружения с той же проблемой),
Существует ли лучший подход или рекомендуемый шаблон для обработки событий перекрестного потока?
Нет, нет. Нить может просто выполнять обработчик событий, пока вы не регистрируете его и закроете форму. Небольшие шансы, но не ноль. Вы должны остановить поток, прежде чем закрыть форму. Если вы не хотите его прервать, вам придется сохранить форму открытой, отменив событие FormClizing, а затем позвольте обратный вызов потока потока закрыть форму.
Проверьте эта нить для получения дополнительной информации.
Я не использовал рамки с собственным диспетчером событий, но у меня был свой опыт с теми, которые я создал. Вот мой опыт
Этот подход не безопасен. Вызов все еще будет называться, даже если сама программа закрыта. Я видел это в диспетчере задач (после того, как программа закрыта, как вы говорите) как висячие потоки. (Даже если вы также убьете программу от менеджера задач.). Я должен был убить эти нити отдельно позже.
Когда форма закрывается, вы должны убить диспетчерскую нить, чтобы он не повесил, если в этой теме ничего не будет.
Форма. Оценка + = (отправитель, Eargs) => src.onframeworkevent - = form.somecation;
// псевдокод (найти C # эквивалент)
Если (DispatcherThread.isrunning)
DispatcherThread.kill ();