新的异步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/