简体   繁体   中英

Using Async await in Windows Forms Load event to load other data controls?

We have a Windows Forms ParentForm that opens ChildForm . Something like the following:

var form = new ChildForm(parm1, parm2, parm3, parm4);
form.StartPosition = FormStartPosition.CenterParent;
form.ShowDialog();

The constructor for ChildForm looks like this:

public ChildForm(string Parm1, string Parm2, string Parm3, string Parm4)
{
    InitializeComponent();

    FillThisComboBox();
    FillThisOtherComboBox();
    BindAnotherCombobox();
    BindGridview();
    FillCheckBoxList();
    FillAnotherCheckBoxList();
}

Unfortunately, ChildForm takes a while to load because it runs all those methods before actually drawing the Form.

I would like to execute all these methods using async await so the Form is drawn while everything ekse runs, and I've tried something like the following, but I continue getting build errors:

private async void ChildForm_Load(object sender, EventArgs e)
{
    await PrepareControls();
}
private async Task PrepareControls()
{
    FillThisComboBox();
    FillThisOtherComboBox();
    BindAnotherCombobox();
    BindGridview();
    FillCheckBoxList();
    FillAnotherCheckBoxList();
}

Any help is appreciated. Thanks.

There are some rules for Async/Await as follows:

  1. Any method marked as async must either return a void, task, or task of something.
  2. Async Event handlers return void to match the EventHanlder defintion/signature
  3. Making the other methods async usually follows this pattern:

     public async Task<ofSomething> DoSomething(){ //entry here is on the caller's thread. var x =await Task<ofSomething>.Run(()=>{ //this code will be run independent of calling thread here return GetSomething(); } //at this point you are back on the caller's thread. //the task.result is returned. return x; }

Where each async method has one or more statements that "await" a value. The variable x is "Closing over the task that is returning the result of GetSomething of type OfSomeThing.

To use the code above say in an eventhanlder that returns void...as you already know you must put in the async keyword

public async void ClickEventHandler(object sender, EvantArgs e){
    var x = await DoSomething();
    //var x now has the ofSomething object on the gui thread here.
}

Note that the click handler returns void to meet the delegate signature for the clickhandler, but it calls an async method that does NOT return void.

Concurrency, Error Handling and Cancellation are all important so study up on those as well. Welcome to the world of Async. The Async world has made things much easier.

WARNING ALWAYS DO THIS

In 2012 Stephen Cleary wrote about Configure.Await(false) .

I subsequently in a real application learned to ensure this was always done. It speeds things up considerably and avoids other issues.

See my two form project. You can call the PrepareControls after the constructor and load functions by using an instance of the form. You can use form.Show() or form.ShowDialog() depending if you want to wait for child form to close or not to close.

Form 1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Form2 form2;
        public Form1()
        {
            InitializeComponent();
            form2 = new Form2(this);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            form2.Show();
            string  results = form2.GetData();
        }
    }
}

Form 2

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        Form1 form1;
        public Form2(Form1 nform1)
        {
            InitializeComponent();

            this.FormClosing +=  new FormClosingEventHandler(Form2_FormClosing);
            form1 = nform1;
            form1.Hide();
        }
        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            //stops form from closing
            e.Cancel = true;
            this.Hide();
        }
        public string GetData()
        {
            return "The quick brown fox jumped over the lazy dog";
        }

    }
}

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