Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用while循环取消查询将永远挂起_C#_.net_Sql Server_Async Await_Cancellation - Fatal编程技术网

C# 使用while循环取消查询将永远挂起

C# 使用while循环取消查询将永远挂起,c#,.net,sql-server,async-await,cancellation,C#,.net,Sql Server,Async Await,Cancellation,我试图使用查询取消(通过取消令牌)来取消长时间运行的复杂查询。我发现,在某些情况下,取消操作不仅无法停止查询,而且对CancellationToken.Cancel()的调用也会无限期挂起。下面是一个复制此行为的简单复制程序(可以在LinqPad中运行): 有趣的是,在SQLServerManagementStudio中运行的同一查询会通过“CancelExecutingQuery”按钮立即取消 如果查询取消不能取消,是否有一些警告 我的SqlServer版本: Microsoft SQL Se

我试图使用查询取消(通过取消令牌)来取消长时间运行的复杂查询。我发现,在某些情况下,取消操作不仅无法停止查询,而且对
CancellationToken.Cancel()
的调用也会无限期挂起。下面是一个复制此行为的简单复制程序(可以在LinqPad中运行):

有趣的是,在SQLServerManagementStudio中运行的同一查询会通过“CancelExecutingQuery”按钮立即取消

如果查询取消不能取消,是否有一些警告

我的SqlServer版本:

Microsoft SQL Server 2012-11.0.2100.60(X64) 2012年2月10日19:39:15 版权所有(c)微软公司 Windows NT 6.2(内部版本9200:)上的快速版(64位)

我在Windows 10上运行,.NET的
环境。版本为4.0.30319.42000

编辑

一些补充资料:

以下是当
cancellationToken.Cancel()挂起时从Visual Studio中提取的堆栈跟踪:

另一条线卡在这里:

此外,我尝试更新到SQLServerExpress 2017,我看到了相同的行为

编辑


我将此作为一个bug提交给corefx:

我可以在控制台应用程序中重现此问题。(问题中的代码是来自LINQPad的代码。)

我将回答这个问题,并说这是ADO.NET中的一个bug。ADO.NET应向SQL Server发送查询取消信号。我可以从CPU使用情况看出,SQL Server继续执行循环。因此,它没有收到客户的取消通知。我们还知道SSMS能够取消此循环

当循环运行时,我可以看到控制台应用程序使用了一个CPU核心的50%,并以70MB/秒的速度从SQL Server接收数据。我不知道这是什么数据。可能是行数信息或其他相关信息

我认为这个错误与循环不断发送数据有关,因此ADO.NET从来没有机会发送取消。它仍然是一个bug,如果你报告它,它将是一个社区服务。你可以链接到这个问题

如果循环使用

            WHILE 1 = 1
            BEGIN
                DECLARE @x INT = 1
                WAITFOR DELAY '00:00:01' --new
            END
。。。那么取消很快

此外,你一般不能指望取消很快。如果网络断开,客户端可能需要30秒才能注意到并抛出

因此,您需要对程序进行编码,使其继续执行,而不是等待查询完成。它可能是这样的:

var queryTask = ...;
var cancellationToken = ...;

await Task.WhenAll(queryTask, cancellationToken);

这样一来,取消看起来总是即时的。确保资源仍处于处置状态。所有SQL交互都应该封装在
queryTask
中,这样它就可以在后台继续并最终清理干净。

我更担心SQL中的
WHILE循环
,它挂起的原因是一个较小的问题。最有可能的是SqlServer Management Studio不使用
SqlConnection
SqlCommand
,因此它很有可能通过其他方式立即取消查询。是否有一个无论如何都不会返回任何内容的无限循环?您可以尝试添加命令timeout@M.Ali我在这里展示一个玩具盒,试图找出一个技术限制或缺陷。实际上,我认为查询取消挂起是一个相当大的问题。想象一下,如果有人试图在ADO.NET上实现一个类似SSMS的工具?这将是一个大问题。@MickyD命令超时将导致查询退出,但只有在超时过期之后。在我的用例中,超时很长是合适的,因此如果操作最终不需要,我依靠取消在该点之前中止查询。同样,在实际情况中,循环并不是真正无限的,但在某些情况下需要足够长的时间才能终止,这是正确的。我已经在这里向MSFT提交了错误:
var queryTask = ...;
var cancellationToken = ...;

await Task.WhenAll(queryTask, cancellationToken);