Упомянутые вами исключения не имеют никакого отношения к BackgroundWorker
, за исключением того, что один поток (рабочий) пытается получить доступ к элементам управления, которые были удалены другим потоком (UI).
Решение, которое я бы использовал, заключается в том, чтобы прикрепить обработчик события к событию Form.FormClosed
, чтобы установить флаг, который сообщает вам, что пользовательский интерфейс был разрушен.Затем дескриптор RunWorkerCompleted
проверит, не сорван ли пользовательский интерфейс, прежде чем пытаться что-либо делать с формой.
Хотя этот подход, вероятно, будет работать более надежно, чем проверка IsDisposed
, если вы этого не сделаетеЯвное удаление формы не дает 100% гарантии того, что форма не будет закрыта и / или удалена сразу после того, как код очистки проверил флаг и обнаружил, что он все еще там.Это условие гонки, о котором вы сами упомянули.
Чтобы устранить это состояние гонки, вам необходимо выполнить синхронизацию, например, так:
// set this to new object() in the constructor
public object CloseMonitor { get; private set; }
public bool HasBeenClosed { get; private set; }
private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
lock (this.CloseMonitor) {
this.HasBeenClosed = true;
// other code
}
}
и для работника:
worker.RunWorkerCompleted += (sender, args) => {
lock (form.CloseMonitor) {
if (form.HasBeenClosed) {
// maybe special code for this case
}
else {
cleanup();
// and other code
}
}
};
Событие Form.FormClosing
также будет отлично работать для этой цели, вы можете использовать любое из двух удобнее, если оно имеет значение.
Обратите внимание, что способ написания этого кода,Оба обработчика событий будут запланированы для выполнения в потоке пользовательского интерфейса (это связано с тем, что компоненты WinForms используют однопотоковую модель квартиры), поэтому на самом деле на вас не будет влиять состояние гонки.Однако, если вы решите создать больше потоков в будущем, вы можете выставить условие гонки, если вы не используете блокировку.На практике я видел, что это случается довольно часто, поэтому я предлагаю синхронизацию в любом случае, чтобы быть перспективным.На производительность это не повлияет, поскольку синхронизация происходит только один раз.