如何取消长时间运行的数据库操作?

Rob*_* P. 26 .net database oracle asynchronous backgroundworker

目前正在与Oracle合作,但也需要一个MS SQL解决方案.

我有一个GUI,允许用户生成将在数据库上执行的SQL.这可能需要很长时间,具体取决于它们生成的搜索.我希望GUI/App在此搜索期间能够响应,我希望用户能够取消搜索.

我正在使用后台工作线程.

我的问题是,当用户取消搜索时,我无法中断对数据库的调用.它等待它完成然后,它可以轮询'CancelationPending'属性.这不仅浪费了数据库上的资源,而且还为我的代码带来了问题.

如果用户在非常长的查询中点击"搜索",则再次点击"取消",然后再次"搜索" - 第一次搜索仍然在数据库上进行搜索.后台工作人员再次点击搜索时仍然很忙.我遇到这个问题的唯一方法就是建立一个新的后台工作者.

这似乎是一种非常丑陋的做事方式.数据库继续工作我正在创建后台工作者的新实例....当我真的想要停止数据库调用并重新使用同一个worker时.

我怎样才能做到这一点?

Meh*_*ras 10

如果您正在使用ADO.NET和SQL数据提供程序,请查看SqlCommand.Cancel方法.这就是你想要的.但是,它会尝试取消,取消可能需要一些时间.基本上,由SQL Server决定何时授予您的取消请求.取消查询时,您应该获得一个SqlException,指示操作已被用户取消.显然,您不希望将此异常视为异常并特别处理它,例如,如果SqlException是由于用户取消操作而导致的,只需将其吞下即可.


Koe*_*oen 8

我还注意到command.Cancel()并没有真正中止命令.对我来说有用的是当用户中止时关闭连接(如果你使用了回滚事务).这将在命令执行时在后台线程中引发异常,因此您必须捕获它并检查那里的CancellationPending属性,而不是在这种情况下重新抛出异常...

// When aborting
worker.CancelAsync();
command.Connection.Close();

// In your DoWork event handler
...
catch (Exception)
{
    if (worker.CancellationPending)
    {
        e.Cancel = true;
        return;
    }
    else
    {
        throw;
    }
}

// And in your RunWorkerCompleted event handler
if (e.Error == null && !e.Cancelled)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)


Jos*_*ons 5

我很确定它是可行的 - 我们使用TOAD for Oracle,它可以让你取消长时间运行的查询,如下所述.我不确定他们是怎么做的.


Jos*_*ren -2

我认为这是不可能的。以下是 Oracle 网站上有关此主题的讨论的链接: http://forums.oracle.com/forums/thread.jspa ?threadID=400492&start=15&tstart=0