【问题标题】:Exception handling with Async Task functions使用异步任务函数处理异常
【发布时间】:2019-08-20 06:59:56
【问题描述】:

我开始学习在 VB.NET 中运行可取消 SQL 查询的异步/任务函数。

我在一个类库中有以下代码,它运行两个任务并且没有任何异常处理,因为我想在调用类库的应用程序中处理这个。我在类库中有以下代码。

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 之外运行时,异常处理会按预期工作。

这似乎与在调试器中运行时的正常行为不同 - 通常异常处理会运行,但只有在未处理异常时才会中断。

为什么这种行为不同,大概是因为异步函数?

【问题讨论】:

  • 然后返回一个你可以处理的任务……

标签: vb.net exception async-await


【解决方案1】:

在 IDE 中以 Debug 模式运行时,应用仍会中断,并且异常(例如 SqlException)会在 IDE 中显示。

为什么这种行为不同,大概是因为异步函数?

catch 不会直接捕获异步函数抛出的异常。实际发生的是异常被编译器生成的状态机捕获,并且该异常被放置在返回的Task 上。稍后,当等待该任务时,异常会重新引发,然后可以被catch 捕获。

但是,异常处理中的这种“间接性”意味着 IDE 在最​​初抛出异常时确实有些异常。据它所知,您的代码中没有catch 会捕获它,这就是它中断并显示异常的原因。它不知道编译器生成的代码会捕获它。你可以tell the IDE not to worry about uncaught exceptions

【讨论】:

    猜你喜欢
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2012-09-27
    • 2015-07-18
    • 2019-08-29
    • 1970-01-01
    • 2014-03-06
    相关资源
    最近更新 更多