如何取消Ado.Net异步调用?

时间:2019-03-01 17:19:56

标签: c# ado.net

我具有查询数据库的功能

private async Task<IEnumerable<T>)> RunQuery<T>(string sql)
{
    using (var conn = new SqlConnection(_connStr))
    using (var cmd = new SqlCommand(sql, conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandTimeout = 300;
        await conn.OpenAsync().ConfigureAwait(false);
        var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false);
        // ... yield return the result from the reader

某些查询需要很长时间才能运行,因此我需要将其取消(这样它将释放数据库锁,等等)。如何实现?

1 个答案:

答案 0 :(得分:0)

如对问题的评论中所述,请使用带有CancellationToken的重载,因为这样您就可以通过用于生成令牌的CancellationTokenSource触发取消请求。

通过将以下代码放入Windows Forms应用程序来模拟长时间运行的任务,可在工作中看到此结果:

CancellationTokenSource _cts = new CancellationTokenSource();
bool _started = false;

private async void button1_Click(object sender, EventArgs e)
{
    if (!_started)
    {
        _started = true;
        using (var conn = new SqlConnection(_connStr))
        using (var cmd = new SqlCommand("WAITFOR DELAY '00:00:30'", conn))
        {
            cmd.CommandType = CommandType.Text;
            cmd.CommandTimeout = 300;
            await conn.OpenAsync().ConfigureAwait(false);
            var reader = await cmd.ExecuteReaderAsync(_cts.Token).ConfigureAwait(false);

            MessageBox.Show("Done");
        }
    }
    else
    {
        _cts.Cancel();
    }
}

单击表单上的按钮一次将触发对数据库的请求,第二次请求将其取消。确实会引发异常,然后需要对其进行适当处理:

Exception being thrown by the database request being cancelled