Async loading for winforms

15,455

Where am i supposed to place the await keyword to accomplish this? I can't place it in my Load event since this needs to complete for the application to behave "normally".

Why can't you await inside load event handler? You can do that if you mark the method with async modifier.

private async void Form_Load(object sender, EventArgs e)
{
    //Do something
    var data = await GetDataFromDatabaseAsync();
    //Use data to load the UI
}

This way, you can keep the UI responsive and also execute the time consuming work asynchronously. GetDataFromDatabaseAsync has to be asynchronous (should not block the calling thread).

If this doesn't answers your question, please be more specific.

Share:
15,455
H W
Author by

H W

Updated on June 20, 2022

Comments

  • H W
    H W almost 2 years

    In (Android) Apps it is quite common to have ListViews loading and being built while the user is interacting with the interface. In Winforms however the tendency seems to be clicking a button and waiting for the result to be fully loaded before the user can continue navigating through the application.

    Since the database access that i am currently using is quite slow, i would like to use the database in async methods to enable the user to keep interacting with the interface, while the data is not fully loaded and displayed.

    For example i would like to start an asynchronous method in my Form_Load event to keep gathering data. When this method completes, i want to bind the data to some controls - this will (for now) not change the functionality at all. Thus i want the user not to notice any difference (except for the data being shown or not) when handling the application.

    Where am i supposed to place the await keyword to accomplish this? I can't place it in my Load event since this needs to complete for the application to behave "normally".

    Is it even possible with async methods to have windows forms being fully reactional while not all methods completed, or am i looking at the 'wrong' functionality for my purposes?

    Thank you in advance.

    Edit: Following Srirams hint, I made the load-event itself an async sub which worked out well. Here is some simple sample code which shows the desired behaviour:

    Public Class DelayedLoadingWindow
    
        Private Async Sub DelayedLoadingWindow_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim awaitedResultOne As Task(Of String) = GetDataOneAsync()
            Label1.Text = Await awaitedResultOne
            Dim awaitedResultTwo As Task(Of String) = GetDataTwoAsync()
            Label2.Text = Await GetDataTwoAsync()
            Dim awaitedResultThree As Task(Of String) = GetDataThreeAsync()
            Label3.Text = Await GetDataThreeAsync()
            Me.Text = "DONE"
        End Sub
    
        Public Async Function GetDataOneAsync() As Task(Of String)
            Await Task.Delay(2000)
            Return "Async Methods"
        End Function
    
        Public Async Function GetDataTwoAsync() As Task(Of String)
            Await Task.Delay(2000)
            Return "are"
        End Function
    
        Public Async Function GetDataThreeAsync() As Task(Of String)
            Await Task.Delay(2000)
            Return "running!"
        End Function
    End Class
    
  • Ben Robinson
    Ben Robinson over 9 years
    Whilst this won't block the UI as such, surely the form in question will not load until the event handler completes, which will not be until the GetDataFromDatabaseAsync() completes.
  • Sriram Sakthivel
    Sriram Sakthivel over 9 years
    @BenRobinson From what OP said Thus i want the user not to notice any difference (except for the data being shown or not) that's fine I guess. Also what else you can do about it?
  • Steve
    Steve over 9 years
    DoWork works in a different thread from the UI thread, no message loop there. This will fail in a spectacular way.
  • Stephen Cleary
    Stephen Cleary over 9 years
    @BenRobinson: No, WinForms considers the Form_Load event "done" when it hits the first await. This is an entirely appropriate solution; just make sure that the form is initialized to an "empty state" UI before the first await, and then the code after the first await should just be updating the UI to contain the data.
  • M.G.E
    M.G.E over 9 years
    @StephenCleary I think if we consider this case as general in OOP, what's happening is that you don't know what's happening after Load handler of form, then it can not wait a handler.
  • Vaibhav J
    Vaibhav J over 9 years
    @Steve: i just forget to add Application.Run(frm), now i have updated my code, and its now perfectly working, i have checked it with my test project. Thanks for correct me.
  • Stephen Cleary
    Stephen Cleary over 9 years
    @TommyMoore: I'm not sure what you mean. It's an event, and can be handled asynchronously just fine.
  • Steve
    Steve over 9 years
    Not downvoting you but this is still wrong stackoverflow.com/questions/3892189/…
  • Vaibhav J
    Vaibhav J over 9 years
    @Steve: what is the problem with the code Steve, i m curious to know, i have test it with my test project and i can send it you if you want. pl. let me know the problem.
  • M.G.E
    M.G.E over 9 years
    @StephenCleary Let's assume that I have a Custom form that it has a custom OnFormLoad and after the Load event runs some jobs then if we handle Load like that we wait the jobs after Load event. It's attractive because it's new feature in c# but not the robust and neat solution like running a Task in a new thread.
  • Sriram Sakthivel
    Sriram Sakthivel over 9 years
    @TommyMoore What do you mean? Are you sure you know enough about async/await ? What makes Task a robust and neat which async/await isn't?
  • Sriram Sakthivel
    Sriram Sakthivel over 9 years
    @Vaibhav Now your DoWork event can't do any other work than pumping the message which makes the BackgroundWorker useless.
  • Steve
    Steve over 9 years
    And if you look at the not accepted answer in the link posted you will discover the problems with drag.drop and copy.paste
  • H W
    H W over 9 years
    Thank you, apparently i was just lacking some very basics of async methods. Stephens hint was very helpful as well!
  • Sriram Sakthivel
    Sriram Sakthivel over 9 years
    @HW Welcome. StephenCleary's blog is a good place to start learning async/await. Cheers!.
  • erict
    erict about 6 years
    I thought doing "async void" is a sin? see Haack's haacked.com/archive/2014/11/11/async-void-methods
  • Sriram Sakthivel
    Sriram Sakthivel about 6 years
    @erict yes it is with the exception of event handlers. Just because you can't have the event handlers return a Task, its okay to have async void there. But we should handle the exceptions inside the method as no one is waiting for the task.