【发布时间】:2018-01-26 12:40:15
【问题描述】:
我正在尝试使用查询取消(通过取消令牌)来取消长时间运行的复杂查询。我发现在某些情况下,取消不仅无法停止查询,而且对CancellationToken.Cancel() 的调用也会无限期挂起。这是一个复制此行为的简单重现(可以在 LinqPad 中运行):
void Main()
{
var cancellationTokenSource = new CancellationTokenSource();
var blocked = RunSqlAsync(cancellationTokenSource.Token);
blocked.Wait(TimeSpan.FromSeconds(1)).Dump(); // false (blocked in SQL as expected)
cancellationTokenSource.Cancel(); // hangs forever?!
Console.WriteLine("Finished calling Cancel()");
blocked.Wait();
}
public async Task RunSqlAsync(CancellationToken cancellationToken)
{
var connectionString = new SqlConnectionStringBuilder { DataSource = @".\sqlexpress", IntegratedSecurity = true, Pooling = false }.ConnectionString;
using (var connection = new SqlConnection(connectionString))
{
await connection.OpenAsync().ConfigureAwait(false);
using (var command = connection.CreateCommand())
{
command.CommandText = @"
WHILE 1 = 1
BEGIN
DECLARE @x INT = 1
END
";
command.CommandTimeout = 0;
Console.WriteLine("Running query");
await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
}
}
}
有趣的是,在 SqlServer Management Studio 中运行的相同查询会通过“取消执行查询”按钮立即取消。
在无法取消紧凑的 WHILE 循环的情况下查询取消是否有一些警告?
我的 SqlServer 版本:
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 2012 年 2 月 10 日 19:39:15 版权所有 (c) 微软公司 Windows NT 6.2(内部版本 9200:)上的 Express 版(64 位)
我在 Windows 10 上运行,.NET 的 Environment.Version 是 4.0.30319.42000。
编辑
一些附加信息:
这是cancellationToken.Cancel() 挂起时从 Visual Studio 中提取的堆栈跟踪:
另一个线程卡在这里:
此外,我尝试更新到 SqlServer Express 2017 并看到相同的行为。
编辑
我已将此作为一个错误提交给 corefx:https://github.com/dotnet/corefx/issues/26623
【问题讨论】:
-
我会更担心我的 SQL 中的
WHILE LOOP,它为什么挂起是一个较小的问题。 -
SqlServer Management Studio 很可能不使用
SqlConnection和SqlCommand,因此很有可能它可以通过其他方式立即取消查询 -
拥有一个不返回任何内容的无限循环有多现实?您可以随时尝试添加命令超时
-
@M.Ali 我在这里展示了一个玩具箱,试图找出技术限制或错误。我实际上认为查询取消挂起是一个很大的问题。想象一下,如果有人试图在 ADO.NET 之上实现类似 SSMS 的工具?这将是一个大问题。
-
@MickyD 命令超时将导致查询退出,但仅在超时到期后。在我的用例中,超时相当长是合适的,因此如果最终不需要操作,我将依靠取消来在该点之前中止查询。同样,在真实情况下,循环并不是真正的无限循环,而是在某些情况下需要足够长的时间才能终止,因此这个问题很明显。
标签: c# .net sql-server async-await cancellation