Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call async method from MainWindow?

So I wrote a quick async method to get some data into a DataTable from an Oracle db. How am I suppose to call this from MainWindow() without blocking UI thread? The async/wait model doesn't really make much sense there.

    async Task<DataTable> AccessOracleAsync()
    {
        DataTable dt;
        using(OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
        {
            await conn.OpenAsync();
            using (var reader = await cmd.ExecuteReaderAsync())
            {
                dt = new DataTable();
                dt.Load(reader);                        
            }

        }
        return dt;
    }
like image 902
user17753 Avatar asked Dec 11 '22 00:12

user17753


2 Answers

Without seeing your constructor, it's hard to say what might "make sense" there. But you have at least a couple of options here.

Option #1: put the call in the constructor.

In this case, you can't make the method async, and you most certainly don't want your continuation to do anything that needs to be done before the constructor returns. But you can still do effectively what C# would have done for you in an async method:

public MainWindow()
{
    InitializeComponent();

    AccessOracleAsync().ContinueWith(task => { /* do some other stuff */ },
        TaskScheduler.FromCurrentSynchronizationContext());
}

That will execute the continuation on the UI thread, as if you had written await AccessOracleAsync(); /* do some other stuff */. Add exception handling in the continuation method as necessary (i.e. inspect the task object and handle appropriately).

Option #2: put the call somewhere else.

It has been suggested to use the Loaded event, which you can do. That might look something like this:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    await AccessOracleAsync();

    // do some other stuff
}

Note that if the latter seems appropriate, IMHO it's preferable. It lets the C# compiler do the heavy-lifting for you, including dealing with exceptions (you can just wrap the call in try/catch and everything "just works").

like image 54
Peter Duniho Avatar answered Dec 31 '22 00:12

Peter Duniho


Try creating a handler for the Laoded event, marking it as async and call your AccessOracleAsync method from there.

like image 31
MotoSV Avatar answered Dec 30 '22 23:12

MotoSV