I have a Windows Forms application and a Form with many async void event handlers. This form can be closed by the user at any moment. After closing the form I want to delete a temporary file, and my problem is that the file might still be used by some async void event handler of my form, resulting in an IOException. The code that deletes the file is placed immediately after the Application.Run(form) call inside the Main method. My question is: how can I force the Application.Run method to keep blocking the Main execution flow, until all async void event handlers of my form are completed?
Here is a minimal demonstration of the desirable behavior:
[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}"); } The desirable output is:
Completed operations: 2 Both async void operations should always be completed when the execution flow reaches the final MessageBox.Show line. The actual (undesirable) output of the above code depends on how quickly the user will close the window. If she closes it in less than two seconds, only 0 or 1 operations might be completed.
Clarifications: Configuring the Task.Delay(1000) with .ConfigureAwait(false) is not an option. My actual event handlers interact with UI components, so it's mandatory to resume on the UI thread after the await. The code below the Application.Run(form) should also run on the UI thread. I don't want to introduce multithreading in my application.
Edit: I am looking for the "correct" way to solve this problem. I am not looking for a dirty workaround. I could probably solve my specific problem of the IOException by doing a busy loop after the Application.Run:
while (true) { try { File.Delete(path); break; } catch { } Application.DoEvents(); } I am looking for something better/cleaner/less-smelly than this.
async voidis fire and forget, you need some way to keep track of what's going on.SemaphoreSlimidea is not ideal, feel free to post an answer that shows a solution to the minimal problem in my question, if you want.