Забавно, это мой связанный вопрос. В любом случае, решение простое. Используйте этот шаблон:
await Whatever();
if (IsDisposed)
return;
Почему это необходимо? Ну, await
вызов захватывает текущий SynchronizationContext
и затем отправляет обратно на него.
Это означает, что вы вернулись в исходную ветку. В этом случае поток GUI.
Несмотря на то, что это происходит асинхронно, объекты GUI могут быть удалены по разным причинам (чаще всего это форма, закрываемая пользователем). Помните, что await
является , а не блокирующим вызовом.
Поэтому вы должны защищаться с помощью IsDisposed
проверок (проверок) каждый раз, когда вы await
в потоке GUI.
В частности, отметьте этот флаг на любых элементах управления, измененных после вызова await
в том же методе (включая Form
, который получен из Control
).
Однако , вам необходимо понять, как задачи обрабатываются с помощью исключений:
Если вы делаете await
, вы можете try ... catch
вокруг него. Если вы не используете await
, исключения не всплывают. Вот простой пример.
Task.Run(() => { ... });
Это не вызовет исключение, которое вы можете поймать , если не ожидается. Если вы не используете await
, вы можете проверить исключение, используя Task.Exception
, например:
var task = Task.Run(() => { ... });
//...SNIP...
if (task.Exception != null)
//Do something
Другие проблемы с вашим кодом:
public async void StartCheck(Form1 caller)
должно быть
public async Task StartCheck(Form1 caller)
Только время, когда метод asyn c не должен возвращать Task
или Task<T>
, если вам не разрешено использовать эту подпись (например, обработчики нажатия кнопок).
Наконец, используйте Task.Delay
, а не Thread.Sleep
. Измените
await Task.Run(() =>
{
Thread.Sleep(10000);
});
на
await Task.Delay(10000);
Редактировать
Попробуйте:
public async Task startCheck(Form1 caller)
{
await Task.Delay(10000);
this.Show();
}
После закрытия newForm
, но до завершения await
. Будет сгенерировано исключение.
Это также должно вызвать ожидаемое поведение:
newForm.Dispose(true);