新的异步ExecuteReaderAsync采用CancellationToken。有什么办法可以取消旧的同步ExecuteReader

在我们的例子中,所有数据操作都是在后台线程上同步的,因此await不是一个选项。我不想启动第二个线程-Task.Run(() => command.ExecuteReaderAsync(token)).Result只是为了能够从UI线程中取消似乎是一种浪费。

最佳答案

性能测试表明,与使用具有线程池连续性的Begin或Async API相比,使用专用的同步数据读取线程将使性能提高近2倍。 (由于将在几秒钟内加载数千万行,因此在这种情况下,我们更喜欢性能。)

用于方便令牌传递的扩展方法:

public static SqlDataReader ExecuteReader(this SqlCommand command, CommandBehavior commandBehavior, CancellationToken cancellationToken)
{
    try
    {
        using (cancellationToken.Register(command.Cancel))
            return command.ExecuteReader(commandBehavior);
    }
    catch (SqlException) when (cancellationToken.IsCancellationRequested)
    {
        throw new OperationCanceledException(cancellationToken);
    }
}


我对Reflector反编译做了一些摸索。 Begin和Async版本都非常节省,但是它们都完全基于TPL异步。因此,在这两个线程上都有用于连续的线程池调度。

此扩展方法没有线程开销。在令牌源上调用Cancel的线程也将调用command.Cancel,这将立即在数据线程中导致SqlException

关于c# - 是否可以在ExecuteReader中使用CancellationToken?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23685751/

10-11 01:14