What is the best way to catch "Operation cancelled by user" exception

7

i have following peace of code:

IAsyncResult beginExecuteReader = command.BeginExecuteNonQuery();

while (!beginExecuteReader.IsCompleted)
{
    if (controllerTask.CancellationTokenSource.IsCancellationRequested)
    {
        command.Cancel();
    }

    Thread.Sleep(100);
}

try
{
    result = command.EndExecuteNonQuery(beginExecuteReader);
}
catch (SqlException exception)
{
    if (exception.ErrorCode == OperationCanceled)
    {
        throw new OperationCanceledException();
    }

    throw;
}

How can i identify, that catched exception is caused by operation cancelation. In this case ExecuteNonQuery throws exception with error code 0x80131904, but it's very general exception which can be caused by many reasons. Error message looks like this: {"A severe error occurred on the current command. The results, if any, should be discarded.\r\nOperation cancelled by user."}

I don't see any options except of parsing of error message... Any ideas?

Thanks

PS. Yeah, i know that Cancel command for asyncronyc operation probably is not the best idea, because for .NET 2.0 there was warning on MSDN, but for .NET 4.0 this warning is removed. And i also don't like another implementations when cancel method is called from another thread, as for me it makes code more difficult

c#
ado.net
asked on Stack Overflow Apr 19, 2012 by and85

3 Answers

0

There doesn't seem to be a locale insensitive mechanism to catch just this error. The HResult 0x80131904 is just COR_E_SqlException. The error is initiated at TdsParser.cs:2332 without any unique properties. It is almost the exact same code as :2759 - Unknown Error and :3850 - Unexpected Collation.

Here are the bad solutions I have come up with:

Option 1: Break the good advice of "don't make logic locale sensitive"

using (var con = new SqlConnection("Server=(local);Integrated Security=True;"))
{
    con.Open();

    try
    {
        var sqc = new SqlCommand("WAITFOR DELAY '1:00:00'", con);
        var readThread = Task.Run(() => sqc.ExecuteNonQuery());

        // cancel after 5 seconds
        Thread.Sleep(5000);
        sqc.Cancel();

        // this should throw
        await readThread;

        // unreachable
        Console.WriteLine("Succeeded");
    }
    catch (SqlException ex) when (ex.Number == 0 && ex.State == 0 && ex.Class == 11 
        && ex.Message.Contains("Operation cancelled by user."))
    {
        Console.WriteLine("Cancelled");
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error");
    }
}

Option 2: Assume that no other severe locally generated error matters after a cancel has been issued

using (var con = new SqlConnection("Server=(local);Integrated Security=True;"))
{
    con.Open();

    bool isCancelled = false;
    try
    {
        var sqc = new SqlCommand("WAITFOR DELAY '1:00:00'", con);
        var readThread = Task.Run(() => sqc.ExecuteNonQuery());

        // cancel after 5 seconds
        Thread.Sleep(5000);
        isCancelled = true;
        sqc.Cancel();

        // this should throw
        await readThread;

        // unreachable
        Console.WriteLine("Succeeded");
    }
    catch (SqlException ex) when (isCancelled && ex.Number == 0 && ex.State == 0 && ex.Class == 11)
    {
        Console.WriteLine("Cancelled");
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error");
    }
}
answered on Stack Overflow Aug 9, 2018 by Mitch
-1

So imho you should to do next:

  1. Make a thread where you will use ado (read this Thread example)
  2. Delete Thread.Sleep(100); //Imho never use it
  3. Add to your class static bool muststop=false;
  4. Add to your class public static function to change "muststop"
  5. Change you thread's function to stop it if muststop==true

I hope this help you

answered on Stack Overflow Apr 19, 2012 by Likurg
-2

You can exam exception message in catch block to find which operation was cancelled by user:

try
{
   //your code
}
catch (SqlException ex)
{
  if (ex.Message.Contain("Operation cancelled by user"))
   {
       //Do something here
   }
}
answered on Stack Overflow Jul 10, 2013 by cuong pham

User contributions licensed under CC BY-SA 3.0