잡동사니

반응형

질문

VB.NET에서 취소 가능한 SQL 쿼리를 실행하기위한 Async / Task 함수에 대해 배우기 시작했습니다.

class 라이브러리를 호출하는 응용 프로그램에서 이것을 처리하고 싶기 때문에 두 작업을 실행하고 예외 처리가없는 class 라이브러리에 다음 코드가 있습니다. class 라이브러리에 다음 코드가 있습니다.

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 내에서 디버그 모드로 실행하더라도 앱이 여전히 중단되고 IDE 내에 예외 (예 : SqlException)가 표시됩니다. 내가 밟으면 결국 Catch 로직이 실행됩니다.

애플리케이션이 IDE 외부에서 실행되면 예외 처리가 예상대로 작동합니다.

이것은 디버거에서 실행할 때의 정상적인 동작과 다르게 보입니다. 일반적으로 예외 처리는 실행되지만 예외가 처리되지 않은 경우에만 중단됩니다.

아마도 비동기 함수로 인해이 동작이 다른 이유는 무엇입니까?


답변1

IDE 내에서 디버그 모드로 실행하면 앱이 여전히 중단되고 IDE 내에 예외 (예 : SqlException)가 표시됩니다.

아마도 비동기 함수로 인해이 동작이 다른 이유는 무엇입니까?

비동기 함수에서 발생한 예외는 catch 에 의해 직접 잡히지 않습니다. 실제로 발생하는 것은 컴파일러가 생성 한 상태 머신에서 예외를 포착하고 해당 예외가 반환 된 Task 에 배치된다는 것입니다. 나중에 해당 작업이 대기되면 예외가 다시 발생하고 catch 에 의해 포착 될 수 있습니다.

그러나 예외 처리에서 이러한 "간접"은 예외가 처음에 throw 될 때 IDE가 일종의 깜짝 놀란 것을 의미합니다. 그것이 알 수있는 한, 그것을 잡을 코드에 catch 가 없기 때문에 그것이 깨지고 예외를 표시하는 이유입니다. 컴파일러가 생성 한 코드가 그것을 잡을 것이라는 것을 모릅니다. 잡히지 않은 예외에 대해 걱정하지 않도록 IDE에 알립니다 .



 

 

 

 

출처 : https://stackoverflow.com/questions/55415684/exception-handling-with-async-task-functions

반응형

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band