Обработка исключений с помощью функций Async Task - PullRequest
0 голосов
/ 29 марта 2019

Я начинаю узнавать о функциях Async / Task для запуска отменяемых SQL-запросов в VB.NET.

У меня есть следующий код в библиотеке классов, которая выполняет две задачи и не обрабатывает никаких исключений,как я хотел бы обработать это в приложении, которое вызывает библиотеку классов.У меня есть следующий код в библиотеке классов.

Public Async Function DirectoryList(ct As CancellationToken) As Task(Of List(Of Directory))
    ct.ThrowIfCancellationRequested()

    Dim ds As DataSet
    Dim dirs As List(Of Directory)
    Dim ctUnregister As CancellationTokenRegistration

    ds = Await Task.Run(Function()
                            Using newConnection = New SqlConnection(Me.InitializationData.ConnectionString)
                                Using sqlAdapter = New SqlDataAdapter("DirectoryList", newConnection)
                                    ctUnregister = ct.Register(Sub() sqlAdapter.SelectCommand.Cancel())

                                    With sqlAdapter
                                        .SelectCommand.CommandType = CommandType.StoredProcedure
                                        .SelectCommand.CommandTimeout = Me.InitializationData.CommandTimeout
                                    End With

                                    Dim newDataSet As DataSet = New DataSet()

                                    sqlAdapter.Fill(newDataSet)
                                    Return newDataSet
                                End Using
                            End Using

                            ' Remove the registration we set earlier so the cancellation token can be used normally.
                            ctUnregister.Dispose()
                        End Function, ct)

    dirs = Await Task.Run(Function()
                              Dim dirsResult As New List(Of Directory)

                              Dim tbl As DataTable = ds.Tables(0)

                              For Each row As DataRow In tbl.Select()
                                  ' process the data

                                  ct.ThrowIfCancellationRequested()
                              Next

                              Return dirsResult
                          End Function, ct)

    Return dirs
End Function

Затем я вызываю его следующим образом:

Try
    dirs = Await databaseLibrary.DirectoryList(cts.Token)
    MsgBox("Query complete!")
Catch ex As System.Data.SqlClient.SqlException
    MsgBox("Cancelled (SQL)")
Catch ex2 As OperationCanceledException
    MsgBox("Cancelled")
Catch ex3 As Exception
    MsgBox("Cancelled")
End Try

Функционально, кажется, работает как ожидалось - я могу отменить запросы и исключениягенерируются, как и ожидалось.

Однако я хотел бы обработать исключения, чтобы я мог изящно отменить задачи, но даже при работе в режиме отладки в среде IDE приложение все еще ломается, и исключение (например, SqlException)показано в IDE.Если я включаюсь, в конечном итоге логика Catch запускается.

Когда приложение запускается вне среды IDE, обработка исключений работает, как и ожидалось.

Это кажется отличным от нормального поведения при запуске вотладчик - обычно обработка исключений выполняется, но прерывается только в том случае, если исключение не обработано.

Почему это поведение отличается, предположительно, из-за асинхронных функций?

1 Ответ

0 голосов
/ 01 апреля 2019

при работе в режиме отладки в среде IDE приложение по-прежнему прерывается, и в среде IDE отображается исключение (например, SqlException).

Почему это поведение отличается, предположительно, из-за асинхронных функций?

Исключения, генерируемые асинхронными функциями, не * напрямую обрабатываются catch. На самом деле происходит то, что исключение перехватывается сгенерированным компилятором конечным автоматом, и это исключение помещается в возвращенный Task. Позже, когда ожидается это задание, исключение повторно вызывается, и затем может быть перехвачено catch.

Однако эта «косвенность» в обработке исключений означает, что среда IDE начинает волноваться при первоначальном возникновении исключения. Насколько он может судить, в вашем коде нет catch, который собирается его перехватить, поэтому он ломается и отображает исключение. Он не знает, что сгенерированный компилятором код его поймает. Вы можете сказать IDE, чтобы она не беспокоилась о необработанных исключениях .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...