16

I need to call a async method from my Form1 constructor. Since a constructor can't have a return type, I can't add a async void. I read that static constructor can be async but I need to call methods from constructor that aren't static, such as InitializeComponent() (since it's the Form's constructor).

The class is:

public partial class Form1 : Form
{
    InitializeComponent();
    //some stuff
    await myMethod();
}

I read this one too but I still don't know how to implement this (in my case) since the method still requires to use async.

soccer7
  • 3,547
  • 3
  • 29
  • 50
Jack
  • 16,276
  • 55
  • 159
  • 284
  • 2
    Read the [Async OOP](http://blog.stephencleary.com/2013/01/async-oop-0-introduction.html) from Stephen Clearly. – Paulo Morgado Mar 15 '15 at 21:49
  • FYI, that link up there actually appears to be calling for async static factory methods as an alternate approach to static constructors using async. In the article it says static constructors *can't* be async – user1664043 Jul 16 '19 at 19:17

5 Answers5

24

Don't do this in the constructor but in the loaded event of the window instead. You can mark the loaded eventhandler as async.

Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
  • Don't you just end up with an `async void WindowLoaded()`, then? Aren't we supposed to avoid `async void`? What would be the difference between just calling a `private async void MyMethodAsync()` from the constructor? – Andy May 09 '17 at 02:16
  • 2
    Event handlers are a special case. http://stackoverflow.com/questions/19415646/should-i-avoid-async-void-event-handlers – Philip Stuyck May 10 '17 at 06:25
9

You can use a static method that returns an instance of your form

public class TestForm : Form
{
    private TestForm()
    {
    }

    public static async Task<TestForm> Create()
    {
        await myMethod();
        return new TestForm();
    }
}
EZI
  • 15,209
  • 2
  • 27
  • 33
  • 1
    I accepted the answer, but I have a question on this. To call `Create()` shouldn't I do `await Create()` if so, I do need mark the constructor as `async` isn't? – Jack Mar 15 '15 at 16:23
  • @Jack Yes you will call it as `await TestForm.Create()`, but constructor doesn't have to be *async* – EZI Mar 15 '15 at 16:41
2

My sample is to call student details from page constructor

1- the calling of navigation page

    void Handle_ItemTapped(object sender, Xamarin.Forms.ItemTappedEventArgs e)
    {
        Student _student = (Student)e.Item;
        Navigation.PushAsync(new Student_Details(_student.ID));

    }

2 - the details page

public partial class Student_Details : ContentPage
{
    public Student_Details(int id)
    {
        InitializeComponent();
        Task.Run(async () => await getStudent(id));
    }

    public async Task<int> getStudent(int id)
    {
        Student _student;
        SQLiteDatabase db = new SQLiteDatabase();
        _student = await db.getStudent(id);
        return 0;
    }
}
0

While common advice dictates you generally shouldn't do it in the constructor, you can do the following, which I have used in apps, such as console apps, where I need to call some existing async code:

DetailsModel details = null; // holds the eventual result
var apiTask = new Task(() => details = MyService.GetDetailsAsync(id).Result); // creates the task with the call on another thread
apiTask.Start(); // starts the task - important, or you'll spin forever
Task.WaitAll(apiTask); // waits for it to complete

Philip is correct that, if you can avoid doing this in a constructor, you should.

Auri Rahimzadeh
  • 2,133
  • 15
  • 21
-6

Task.Run(async () => await YourAsyncMethod());

  • 3
    It's good practice on Stack Overflow to add an explanation as to why your solution should work. For more information read [How To Answer](http://stackoverflow.com/help/how-to-answer). – Fabian Schultz Jan 09 '17 at 17:23