14

CancellationToken で新しい .Net 4.5 Async/Await 機能を使用すると、 (または操作のキャンセルに固有のその他の例外)ではなく、呼び出しSQLExceptionをキャンセルしたときにが返されます。はメッセージの最後に言います。操作をキャンセルするときに、より具体的な例外がスローされることを期待していました。さらに、この予想されるシナリオに対処するには、適切な Try/Catch ハンドラーをどのように作成すればよいでしょうか? 通常は、より一般的な失敗ブロックを使用しますが、メッセージのテキストを取り出して、ユーザーが [キャンセル] ボタンをクリックしただけかどうかを確認する必要があります!? 私は何かが欠けているに違いない。ExecuteNonQueryAsyncOperationCanceledExceptionSQLExceptionOperation cancelled by userSQLException

これは、非同期呼び出しを実行するボタンとキャンセルするボタンの 2 つのボタンを持つ単純な VB WinForm アプリです。1 番目のボタンの Try/Catch はSQLException、2 番目のボタンが Cancel メソッドを呼び出したときにヒットしたことを示しています。

Dim _cts As CancellationTokenSource
Private Async Sub btnLocalTest_Click(sender As Object, e As EventArgs) Handles btnLocalTest.Click
    _cts = New CancellationTokenSource()
    Dim CancelToken As CancellationToken = _cts.Token
    Using sconn As New SqlConnection("server=(local);database=MyDB;user id=MyUser;password=MyPassword")
        sconn.Open()
        Dim SQL As String = some long running SELECT or INSERT statement
        Try
            Using scmd As New SqlCommand(SQL, sconn)
                scmd.CommandTimeout = 300
                Dim i As Integer = Await scmd.ExecuteNonQueryAsync(CancelToken)
            End Using
        Catch exCancel As OperationCanceledException
            LogEvent("Query canceled Exception.") ' This error is *not* thrown on Cancel.  
        Catch ex As SqlClient.SqlException
            LogEvent("Error with query. " & ex.Message)  ' This error *is* thrown on Cancel.  Message includes text 'Canceled by user.'
        End Try
        sconn.Close()
        _cts = Nothing
    End Using
End Sub

Private Sub btnLocalTestCancel_Click(sender As Object, e As EventArgs) Handles btnLocalTestCancel.Click
    If _cts IsNot Nothing Then
        _cts.Cancel()
    End If
End Sub

更新:HttpClient.GetAsyncキャンセルをサポートするメソッドを使用して、別の非同期テストを作成しました。そのタスクをキャンセルすると、OperationCanceledException上記で最初に予想した例外が発生する可能性があります。 Async タスクをキャンセルしたときに、どのような例外が発生するのでしょうか? それとも、各メソッドとその実装に依存していますか?

4

2 に答える 2