Currently working with Oracle, but will also need a solution for MS SQL.
I have a GUI that allows users to generate SQL that will be executed on the database. This can take a very long time, depending on the search they generate. I want the GUI/App to responsive during this search and I want the user to be able to cancel the search.
I'm using a Background Worker Thread.
My problem is that, when the user cancels the search, I can't interrupt the call to the database. It waits until it is finished and then, it can poll the 'CancelationPending' property. Not only does this waste resources on the database, but it creates problems for my code.
If the user hits 'Search' on a very long query, then clicks 'Cancel' and then 'Search' again - the first search is still chugging away on the database. The background worker is still busy when they hit search again. The only solution I've got to this problem is to make a new background worker.
It seems like a really ugly way to do things. The database keeps working I'm creating new instances of background workers....when I really want to STOP the database call and re-use the same worker.
How can I do that?
In Object Explorer, connect to the instance of the Database Engine, right-click SQL Server Agent, and then select Start, Stop, or Restart.
To kill a session: In SQL Developer, click Tools, then Monitor Sessions. In the Select Connection dialog box, select a connection to SYSTEM (or another account with full DBA privileges) Right-click in the row for the session to be terminated, and select Kill Session.
SQL Server Management Studio Activity Monitor Once Activity Monitor has loaded, expand the 'Processes' section. Scroll down to the SPID of the process you would like to kill. Right click on that line and select 'Kill Process'. A popup window will open for you to confirm that you want to kill the process.
If you're using ADO.NET and SQL data provider, take a look at SqlCommand.Cancel method. That does what you're looking for. However, it tries to cancel and the cancellation may take time. Basically, it's up to SQL Server to decide when to grant your cancellation request. When the query is cancelled, you should get a SqlException that indicates that the operation was cancelled by user. Apparently, you don't want to treat this exception as exception and handle it specially such as if SqlException is due to user cancelling the operation, just swallow it.
I also noticed command.Cancel() doesn't really abort the command. What worked for me is closing the connection (rollback transaction if you use one) when the user aborts. This will raise an exception in your background thread while the command is executing, so you have to catch it and check the CancellationPending property there and not rethrow the exception in that case...
// 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) { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With