Async showdialog

I use async / await to asynchronously load my data from the database and during the upload process, I want to pop up on the upload form, it's just a simple progress bar form to indicate what works there. After loading the data, the dialog box will be automatically closed. How can i achieve this? Below is my current code:

protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.ShowDialog() // not working var data = await GetData(); _progress.Close(); } 

Updated:

I managed to get it to work by changing the code:

  protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.BeginInvoke(new System.Action(()=>_progress.ShowDialog())); var data = await GetData(); _progress.Close(); } 

Is this right or are there any better ways?

Thank you for your help.

+7
c # asynchronous async-await
source share
5 answers

It is easy to implement using Task.Yield like this (WinForms, no exceptions for simplicity):

 namespace WinFormsApp { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } async Task<int> LoadDataAsync() { await Task.Delay(2000); return 42; } private async void button1_Click(object sender, EventArgs e) { var progressForm = new Form() { Width = 300, Height = 100, Text = "Please wait... " }; var progressFormTask = progressForm.ShowDialogAsync(); var data = await LoadDataAsync(); progressForm.Close(); await progressFormTask; MessageBox.Show(data.ToString()); } } internal static class DialogExt { public static async Task<DialogResult> ShowDialogAsync(this Form @this) { await Task.Yield(); if (@this.IsDisposed) return DialogResult.OK; return @this.ShowDialog(); } } } 

It is important to understand how the thread jumps to a new nested message loop (modal dialog), and then returns to the original message loop (for which await progressFormTask ).

+5
source share

Here is a form that uses Task.ContinueWith and should avoid any race condition using modal ProgressForm:

 protected async void LoadDataAsync() { ProgressForm _progress = new ProgressForm(); // 'await' long-running method by wrapping inside Task.Run await Task.Run(new Action(() => { // Display dialog modally // - Use BeginInvoke here to avoid blocking // and illegal cross threading exception this.BeginInvoke(new Action(() => { _progress.ShowDialog(); })); // Begin long-running method here LoadData(); })).ContinueWith(new Action<Task>(task => { // Close modal dialog // - No need to use BeginInvoke here // because ContinueWith was called with TaskScheduler.FromCurrentSynchronizationContext() _progress.Close(); }), TaskScheduler.FromCurrentSynchronizationContext()); } 
+1
source share

ShowDialog() - blocking call; execution will not advance to the await statement until the user closes the dialog box. Use Show() instead. Unfortunately, your dialog box will not be modal, but it will correctly track the progress of the asynchronous operation.

0
source share

Consider downloading ProgressForm data. Your ProgressForm will become LoadDataForm, the task of which is to load data at startup, show the download progress to the operator and, possibly, give the operator the ability to cancel the download:

 protected void OnButtonLoadData_Clicked(object sender, ...) { using (var loadDataForm = new loadDataForm()) { loadDataForm.LoadingParameters = myLoadingParameters; var dialogResult = loadDataForm.ShowDialog(this); if (dialogResult = DialogResult.Ok) { var loadedData = loadDataForm.LoadedData; ProcessData(loadedData); } } } 

When loading a download data form, initialize the progress bar, run the task to load data and a timer to update the progress bar, or let the download task update the progress bar. When the download is complete, the data download task closes the dialog box.

If revocation is required: create a CancellationTokenSource, get a token from this source and pass the token as a parameter for the task. At the end of the event, cancel the cancelationTokenSource function and wait until the task is completed. Let the task regularly check the token if revocation is required.

-one
source share

You can try the following:

 protected async void LoadData() { ProgressForm _progress = new ProgressForm(); var loadDataTask = GetData(); loadDataTask.ContinueWith(a => this.Invoke((MethodInvoker)delegate { _progress.Close(); })); _progress.ShowDialog(); } 
-2
source share

All Articles