1

目前,我有几个查询需要按顺序运行(一些创建临时表,我在以后的查询中从中提取)。

查询在一个BackgroundWorker线程中运行,目前如果有CancellationPending,我会在查询调用之间中断该方法。

但是这种方法是有问题的,因为有时单个查询可以运行很长时间或永远不会返回,所以我需要能够在轮询时运行每个查询BackgroundWorker.CancellationPending

在这种情况下使用的最佳异步模式是什么?我需要DataTable为每个查询填写一个,但如果需要太长时间,仍然可以取消。

4

2 回答 2

1

在所有情况下,合作中止。甚至不要考虑使用Thread.Abort.

伟大的 Stephen Toub 写了一个最佳实践。

TL;DR:当超时计时器触发时,您Task立即完成并让 SQL 查询继续运行。你只是忽略它。

于 2013-01-21T22:39:23.660 回答
1

编辑:最终为我工作的解决方案是使用异步 ADO.NET 方法。BeginExecute...EndExecute...

这是一段在检查 aBackgroundWorker是否请求取消时异步执行查询的代码片段。如果查询运行完成,该函数返回 true,如果执行取消,则返回 false。

代码应该从BackgroundWorker'sDoWork函数中的某个地方调用。

SqlCommand command = new SqlCommand(query, connectionObj);
IAsyncResult result = command.BeginExecuteReader();  // end async execution

// check for user cancellation while result is not complete
while (!result.IsCompleted)
{
    if (myBackgroundWorker.CancellationPending)
    {
        command.Cancel();  // cancel the existing command
        try
        {
             command.EndExecuteReader(result);  // cancel async execution
        }
        catch (SqlException e)
        {
            // will always enter here due to command.Cancel()
            // this is expected
        }

        return false;
    }

    Thread.Sleep(100);  // sleep so loop doesn't consume all the resources
}

// result is complete, do something with data
using (SqlDataReader reader = command.EndExecuteReader(result))
{
    DataTable table = new DataTable();
    table.Load(reader);
}

// do something with table
return true;
于 2013-01-22T19:56:33.970 回答