如何正确捕获异步任务?

时间:2017-01-13 03:38:14

标签: c# async-await try-catch

我想知道为什么这个Click事件中的异常没有被捕获?除了statusLabel向用户显示进程状态之外,代码中没有任何内容。 myDataTable是一个局部变量;目标是将结果分配给它。

GetDataTable也必须是异步的吗?

public DataTable GetDataTable(string connectionString, string cmdText)
{
    DataTable dt = new DataTable();
    using (SqlConnection conn = new SqlConnection(connectionString)) {
        using (SqlCommand comm = new SqlCommand(cmdText, conn)) {
            conn.Open();
            dt.Load(comm.ExecuteReader);
            return dt;
        }
    }
}

private async void Button1_Click(object sender, EventArgs e)
{
    try {
        statusLabel.Text = "Processing...";

        Task<DataTable> dtTask = Task.Run(() => GetDataTable(connectionString, commandText));
        await dtTask;
        myDataTable = dtTask.Result;

        statusLabel.Text = "Done!";
    } catch (Exception ex) {
        MessageBox.Show("Error");
    }
}

更新

我设法通过GetDataTable()返回Task DataTable并将.Open.ExecuteReader更改为异步对应方来解决此问题。对于另一种方法,Try块中的那三行减少为一行:

myDataTable = await GetDataTable(connectionString, commandText);

感谢每个人的耐心!

2 个答案:

答案 0 :(得分:1)

不使用Task.Run将同步方法转换为异步方法,而是使用ExecuteReaderAsync真正异步加载数据。之后,您的代码变得更加简单:

public async Task<DataTable> GetDataTable(string connectionString, string cmdText)
{
    DataTable dt = new DataTable();
    using (SqlConnection conn = new SqlConnection(connectionString)) {
        using (SqlCommand comm = new SqlCommand(cmdText, conn)) {
            conn.Open();
            var reader=await comm.ExecuteReaderAsync();
            dt.Load(reader);
            return dt;
        }
    }
}

private async void Button1_Click(object sender, EventArgs e)
{
    try {
        statusLabel.Text = "Processing...";

        myDataTable = await GetDataTable(connectionString, commandText);

        statusLabel.Text = "Done!";
    } catch (Exception ex) {
        MessageBox.Show("Error");
    }
}

GetDataTable成为异步方法,异步执行查询并返回一个阅读器:

var reader=await comm.ExecuteReaderAsync();
dt.Load(reader);
return dt;

之后,设置myDataTable变量只需要使用await

myDataTable = await GetDataTable(connectionString, commandText);

答案 1 :(得分:0)

我相信你要找的答案就在这里:Async void exception handling

我假设'Button1_Click'方法是'async void'?:

private async void Button1_Click(object sender, EventArgs e)
{
    ...
}