Async/Await with a WinForms ProgressBar

async-await, asynchronous, c#, multithreading, winforms

Solution

@StephenCleary's answer is correct. Though, I had to make a little modification to his answer to get the behavior what I think OP wants.

public void GoAsync() //no longer async as it blocks on Appication.Run
{
    var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle);
    _progressForm = new Form1();

    var progress = new Progress<int>(value => _progressForm.UpdateProgress(value));

    _progressForm.Activated += async (sender, args) =>
        {
            await Go(progress);
            _progressForm.Close();
        };

    Application.Run(_progressForm);
}

Problem

I've gotten this type of thing working in the past with a BackgroundWorker, but I want to use the new async/await approach of .NET 4.5. I may be barking up the wrong tree. Please advise. Goal: Create a component that will do some long-running work and show a modal form with a progress bar as it's doing the work. The component will get the handle to a window to block interaction while it's executing the long-running work. Status: See the code below. I thought I was doing well until I tried interacting with the windows. If I leave things alone (i.e. don't touch!), everything runs "perfectly", but if I do so much as click on either window the program hangs after the long-running work ends. Actual interactions (dragging) are ignored as though the UI thread is blocked. Questions: Can my code be fixed fairly easily? If so, how? Or, should I be using a different approach (e.g. BackgroundWorker)? Code (Form1 is a standard form with a ProgressBar and a public method, UpdateProgress, that sets the ProgressBar's Value): ``` using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Starting.."); var mgr = new Manager(); mgr.GoAsync(); Console.WriteLine("..Ended"); Console.ReadKey(); } } class Manager { private static Form1 _progressForm; public async void GoAsync() { var owner = new Win32Window(Process.GetCurrentProcess().MainWindowHandle); _progressForm = new Form1(); _progressForm.Show(owner); await Go(); _progressForm.Hide(); } private async Task<bool> Go() { var job = new LongJob(); job.OnProgress += job_OnProgress; job.Spin(); return true; } void job_OnProgress(int percent) { _progressForm.UpdateProgress(percent); } } class LongJob { public event Progressed OnProgress; public delegate void Progressed(int percent); public void Spin() { for (var i = 1; i <= 100; i++) { Thread.Sleep(25); if (OnProgress != null) { OnProgress(i); } } } } class Win32Window : IWin32Window { private readonly IntPtr _hwnd; public Win32Window(IntPtr handle) { _hwnd = handle; } public IntPtr Handle { get { return _hwnd; } } } } ```

Original source