Как заставить Application.Run ждать всех обработчиков асинхронной пустоты?C#

Место общения программистов C#
Ответить
Anonymous
 Как заставить Application.Run ждать всех обработчиков асинхронной пустоты?

Сообщение Anonymous »

У меня есть приложение Windows Forms и форма со множеством обработчиков событий async void. Данная форма может быть закрыта пользователем в любой момент. После закрытия формы я хочу удалить временный файл, и моя проблема в том, что этот файл все еще может использоваться каким-либо обработчиком событий async void моей формы, что приводит к исключению IOException. Код, удаляющий файл, размещается сразу после вызова Application.Run(form) внутри метода Main. Мой вопрос: как я могу заставить метод Application.Run продолжать блокировать поток выполнения Main, пока все обработчики событий async void моей формы не будут завершены?
Вот минимальная демонстрация желаемого поведения:

Код: Выделить всё

[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
int completedOperations = 0;
Form form = new();
form.Load += async (s, e) =>
{
await Task.Delay(1000);
completedOperations++;
};
form.Shown += async (s, e) =>
{
await Task.Delay(2000);
completedOperations++;
};
Application.Run(form);
MessageBox.Show($"Completed operations: {completedOperations}");
}
Желаемый результат:

Код: Выделить всё

Completed operations: 2
Обе операции async void всегда должны завершаться, когда поток выполнения достигает последней строки MessageBox.Show. Фактический (нежелательный) вывод приведенного выше кода зависит от того, насколько быстро пользователь закроет окно. Если она закроет его менее чем за две секунды, может быть выполнено только 0 или 1 операция.
Уточнения: Настройка Task.Delay(1000) с помощью .ConfigureAwait(false) невозможна. Мои фактические обработчики событий взаимодействуют с компонентами пользовательского интерфейса, поэтому обязательно возобновить работу потока пользовательского интерфейса после ожидания. Код под Application.Run(form) также должен выполняться в потоке пользовательского интерфейса. Я не хочу использовать многопоточность в своем приложении.
Изменить: Я ищу «правильный» способ решения этой проблемы. Я не ищу грязного обходного пути. Вероятно, я мог бы решить мою конкретную проблему с IOException, выполнив цикл занятости после Application.Run:

Код: Выделить всё

while (true) { try { File.Delete(path); break; } catch { } Application.DoEvents(); }
Я ищу что-нибудь получше/чище/менее вонючее, чем это.

Подробнее здесь: https://stackoverflow.com/questions/798 ... d-handlers
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»