await ExecuteNonQueryAsync() still blocks my UI

2019-05-23 03:56发布

问题:

I find that my C# app UI hangs when calling an async method, I cannot figure out why.

private async void selectCSVFileButton_Click(object sender, EventArgs e)
{
    ... 
    var results = await ntz.getProductNames();
    ...
}
...
public async Task<List<string[]>> getProductNames()
{
    string fmt = "DRIVER={{NetezzaSQL}};SERVER={0};PORT={1};DATABASE={2};UID={3};PWD={4};";
    ntz = new OdbcConnection(string.Format(fmt, server, port, db, user, password));
    await ntz.OpenAsync();
    qry = "SELECT * FROM ak_db_1 WHERE prod_name_desc='Unknown'";
    OdbcCommand cmd = ntz.CreateCommand();
    cmd.CommandTimeout = 600;
    cmd.CommandText = qry;
    await cmd.ExecuteNonQueryAsync();
    ...
}

My application hangs completely (UI unresponsive) until the cmd.ExecuteNonQueryAsync completes. Any ideas?

回答1:

Per the documentation for OdbcCommand.ExecuteNonQueryAsync:

Providers should override with an appropriate implementation. The cancellation token may optionally be ignored. The default implementation invokes the synchronous ExecuteNonQuery method and returns a completed task, blocking the calling thread.

Derived commands (such as SqlCommand for SQL Server) do override this so the command executes asynchronously.

If you want to avoid blocking the UI thread, then you'll have to execute this on a thread pool thread:

var results = await Task.Run(() => ntz.getProductNames());

Given the asynchronous methods aren't implemented and simply delegate to their synchronous equivalents, it may make sense to change getProductNames to use the synchronous method in the first place.



回答2:

try to add this, instead await ntz.OpenAsync();.

await Task.StartNew(ntz.Open);