You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多Task异步执行失效:程序无异常终止的排查与修复咨询

解决VB.NET异步程序无异常终止问题

以下是针对你代码中异步执行异常终止问题的具体修复方案:

1. 修复主线程未等待异步任务的核心问题

主模块的Main方法是同步方法,调用异步Proses时未等待,导致主线程直接退出,异步任务被强制终止。修改为异步Main并等待任务完成:

Module Main
    Async Sub Main()
        Await Proses()
    End Sub

    Async Function Proses() As Task
        ' 原代码逻辑保持不变
    End Function
End Module

2. 修正ContinueWith的错误用法

AktivitasTeller.Main中ContinueWith同时传入两个Sub参数是语法错误,且ContinueWith不如Await直观易维护,改为直接等待任务后执行后续操作:

Async Function Main(ByVal dataRowAktel As DataRow) As Task(Of String)
    ' 原代码前半部分保持不变
    Await Task.WhenAll(tasks)
    ' 执行后续操作
    GET_CITIZENSHIP_DESC(dataRowAktel("intIDProses"))
    busOtomasi.UpdateIsAktelFinishProses(strConn, 1, dataRowAktel("intIDProses"))
    Return "Success"
Catch ex As Exception
    EmailError($"AktivitasTeller.Main 异常: {ex.ToString}")
    Return "Failed"
End Try
End Function

3. 修复数据库查询未赋值SQL的问题

GetDtTbleDeposito和GetDtTbleRupa中定义了SQL字符串但未赋值给OracleCommand,导致执行空SQL引发异常后被吞,返回空DataTable。补充SQL赋值并完善资源释放:

Async Function GetDtTbleDeposito(ByVal idProsesAktel As Integer, ByVal TglAwal As Date, ByVal TglAkhir As Date, ByVal KdCbg As String, ByVal FlagPlusKCP As Boolean) As Task(Of DataTable)
    Dim strDWH As String = "select * from ***" ' 替换为实际业务SQL
    Dim objOraConn As New OracleConnection(GetConn(Conn.DWH))
    Dim objOraComm As New OracleCommand(strDWH, objOraConn)
    Dim objDtTableDeposito As New DataTable
    Try
        Await objOraConn.OpenAsync()
        Using oraAdapter As New OracleDataAdapter(objOraComm)
            oraAdapter.Fill(objDtTableDeposito)
        End Using
    Catch ex As Exception
        EmailError($"GetDtTbleDeposito 异常: {ex.ToString}")
        Throw ' 重新抛出异常,让上层感知错误
    Finally
        If objOraConn.State = ConnectionState.Open Then
            objOraConn.Close()
        End If
    End Try
    Return objDtTableDeposito
End Function

GetDtTbleRupa方法做同样修改。

4. 移除不必要的线程切换

ProsesData中用Task.Run包裹异步方法AktivitasTeller.Main会造成不必要的线程开销,直接Await异步方法即可:

Async Function ProsesData(ByVal dr As DataRow, ByVal isAktelFinishProses As Integer) As Task(Of Tuple(Of String, DataRow))
    Try
        If isAktelFinishProses = 0 Then
            Dim result = Await AktivitasTeller.Main(dr) ' 去掉Task.Run
            If result = "Success" Then
                ProsesDataAA(dr)
                Return Tuple.Create("success", dr)
            Else
                Console.WriteLine("Task AT Failed")
                Return Tuple.Create("failed", dr)
            End If
        Else
            ProsesDataAA(dr)
            Return Tuple.Create("success", dr)
        End If
    Catch ex As Exception
        EmailError($"Modul Proses Data 异常: {ex.ToString}")
        Return Tuple.Create("failed", dr)
    End Try
End Function

5. 完善异常处理避免吞异常

多个Catch块仅记录错误但不明确传递失败状态,导致问题难以定位。修改为明确返回失败或重新抛出异常:

' 以AddAktelToSQL为例
Catch ex As Exception
    EmailError($"AddAktelToSQL 异常: {ex.ToString}")
    Return "Failed" ' 明确返回失败状态
End Try

6. 优化数据库连接复用

GET_CITIZENSHIP_DESC在循环中频繁开关连接,改为一次性打开连接并复用,同时改为异步方法:

Private Async Function GET_CITIZENSHIP_DESC(ByVal idProses As Integer) As Task
    Dim strConn As String = GetConn(Conn.eOperasional)
    Dim strDWH As String = "select * from **" ' 替换为实际SQL
    Dim objOraConn As New OracleConnection(GetConn(Conn.DWH))
    Dim objOraComm As New OracleCommand(strDWH, objOraConn)
    Dim dtData, dtListCust, dtResult As New DataTable
    Dim busOtomasi As New BusOtomasiSample

    Try
        dtListCust = busOtomasi.GetCisFromAktel(strConn, idProses)
        If dtListCust.Rows.Count > 0 Then
            Await objOraConn.OpenAsync()
            For i = 0 To dtListCust.Rows.Count - 1
                ' 若需参数查询,在此处设置参数
                dtData = New DataTable
                Using oraAdapter As New OracleDataAdapter(objOraComm)
                    oraAdapter.Fill(dtData)
                End Using
                If dtData.Rows.Count > 0 Then
                    dtResult.Merge(dtData.Copy)
                End If
            Next
            busOtomasi.BulkCopyCustomerAktel(strConn, dtResult)
        End If
    Catch ex As Exception
        EmailError($"GET_CITIZENSHIP_DESC 异常: {ex.ToString}")
        Throw
    Finally
        If objOraConn.State = ConnectionState.Open Then
            objOraConn.Close()
        End If
    End Try
End Function

调用时改为:

Await GET_CITIZENSHIP_DESC(dataRowAktel("intIDProses"))

内容的提问来源于stack exchange,提问作者Nicky Apriliani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:40:27