新的异步 ExecuteReaderAsync
采用 CancellationToken。有没有办法取消旧的同步ExecuteReader
?
在我们的例子中,所有数据操作在后台线程上都是同步的,所以 await
不是一个选项。我不想启动第二个线程 - Task.Run(() => command.ExecuteReaderAsync(token)).Result
似乎只是为了能够从 UI 线程取消而浪费。
最佳答案
性能测试表明,与使用 Begin 或 Async API 及其线程池延续相比,使用专用同步数据读取线程的性能优势几乎提高了 2 倍。 (由于数千万行将在几秒钟内加载,因此在这种情况下我们更喜欢性能。)
方便 token 传递的扩展方法:
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 异步。因此,两者都有用于延续的线程池调度。
此扩展方法没有线程开销。在 token 源上调用 Cancel
的线程也会调用 command.Cancel
,这将立即在数据线程中导致 SqlException
。
关于c# - 是否可以将 CancellationToken 与 ExecuteReader 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23685751/