简体   繁体   中英

C# Modal dialog box (ShowDialog or MessageBox.Show) in async method not works as expected

I have a topmost WinForm with a simple button that executes some commands asynchronously:

        private async void button1_Click(object sender, EventArgs e)
    {
        await System.Threading.Tasks.Task.Run(() =>
        {
            System.Threading.Thread.Sleep(2000);

            //Problem1: not works as "modal" dialog box (Main form remains active!) 
            new Form().ShowDialog();

            //Problem2: not shown as "modal" messagebox (Main form remains active!)
            MessageBox.Show("Test");
        });
    }

Inside the async function are the Messagebox.Show() and ShowDialog() methods, BUT:

Problem 1(solved): The new form does not open as modal dialog box (the main form is still active and accessible!)

Problem 2(solved): The MessageBox.Show() method doesn't behave as modal dialog box (the main form is still active and accessible.).

I need async-await to prevent the main UI from freezing, but I also want messageboxes (and sub-forms) inside to be displayed as modal dialog box. How can i show modal dialog boxes (on the main topmost Form) via async method?

Thanks

Solution for problem-1: ShowDialogAsync extension method solves the problem.

Solution for problem-2:

        private async void button1_Click(object sender, EventArgs e)
    {

        var handle = this.Handle;
        await System.Threading.Tasks.Task.Run(() =>
        {
            System.Threading.Thread.Sleep(2000);

            //Solution for Problem2:

            NativeWindow win32Parent = new NativeWindow();
            win32Parent.AssignHandle(handle);
            //Works as expected (Topmost and Modal):
            MessageBox.Show(win32Parent, "Test");
        });
    }

Related topic

Task.Run() runs work in background thread. In common you shouldn't show windows from background threads, but you can. To solve your problem you need to use UI thread Dispatcher.

Application.Current.Dispatcher.Invoke(() => MessageBox.Show("Test"));

Or

Application.Current.Dispatcher.Invoke(() => new Form().ShowDialog());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM