【问题标题】:How do I dispose System.Net.Mail.MailMessage in VB when using SendAsync使用 SendAsync 时如何在 VB 中处理 System.Net.Mail.MailMessage
【发布时间】:2015-01-22 10:03:56
【问题描述】:

我还没有在此处或 MSDN 中找到对此的决定性答案。使用以下代码时,如果我在发送异步邮件后尝试处理消息,则会收到 System.ObjectDisposedException:无法访问已处理的对象。 这是微软示例建议处理的时间。 我无法在回调中处理消息,因为它超出了范围。我曾尝试使用模块级邮件消息,但得到相同的结果。如果我不处理该消息,一切正常,但这不是一个好习惯。请建议处理邮件的最佳位置。

 Public Sub SendEmailWithReport(ByVal v_objEmailAddress As System.Collections.Generic.List(Of String), ByVal v_strSubject As String,
   ByVal v_strBody As String, ByVal v_strFileName As String, ByVal v_intContentID As Integer,
   ByVal v_strType As String) Implements IMessagingPlatform.SendEmailWithReport

    Dim objMessage As New MailMessage
    Dim objAttachment As New Attachment(v_strFileName, MediaTypeNames.Application.Pdf)

    Try
        'configure e-mail addresses and add attachment
        With objMessage
            For Each strAddress As String In v_objEmailAddress
                .To.Add(strAddress)
            Next
            .Attachments.Add(objAttachment)
        End With

        SetUpAsynchEmail(objMessage, v_strSubject, v_strBody, v_strFileName, v_intContentID, v_strType)

    Catch ex As Exception
        Trace.WriteLine(DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") & " : Failed to setup e-mail with report: " & ex.Message.ToString, "ERR")
    Finally
        'objMessage.Dispose() *disposing here gives System.ObjectDisposedException: Cannot access a disposed object.**
        'objAttachment.Dispose()
    End Try
End Sub

Private Sub SetUpAsynchEmail(ByVal v_objMessage As MailMessage, ByVal    v_strSubject As String, ByVal v_strBody As String,
                              ByVal v_strFileName As String, ByVal v_intContentID As Integer, ByVal v_strType As String)
    Dim intID As Integer
    Try
        Dim basicAuthenticationInfo As New System.Net.NetworkCredential(mstrUserName, mstrPassword)
        Dim objClient As New SmtpClient()

        'configure mail message
        With v_objMessage
            .IsBodyHtml = True
            .Subject = v_strSubject
            .Body = v_strBody

            If mstrFromEmailName <> "" Then
                .From = New MailAddress(mstrFromEmailAddress, mstrFromEmailName)
            Else
                .From = New MailAddress(mstrFromEmailAddress)
            End If
        End With

        'configure mail client
        With objClient
            .Host = mstrSMTPHost
            .UseDefaultCredentials = False
            .Credentials = basicAuthenticationInfo
            .EnableSsl = True
            .Port = mintSMTPPort
        End With

        ' Set the method that is called back when the send operation ends. 
        AddHandler objClient.SendCompleted, AddressOf SendCompletedCallback
        'Generate a unique message number
        intID = mobjContainer.AddUnsentMail(v_intContentID, v_strType, v_strFileName)
        If intID > -1 Then
            objClient.SendAsync(v_objMessage, intID)
        End If

        'v_objMessage.Dispose() **disposing here gives System.ObjectDisposedException: Cannot access a disposed object.

    Catch ex As Exception
        Trace.WriteLine(DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") & " : Failed to setup e-mail: " & ex.Message.ToString, "ERR")
    Finally

    End Try
End Sub

Private Sub SendCompletedCallback(ByVal v_objSender As SmtpClient, ByVal e As AsyncCompletedEventArgs)
    ' Get the unique identifier for this asynchronous operation. 
    Dim strMessageID As String = CStr(e.UserState)

    Try
        If e.Cancelled Then
            Trace.WriteLine(DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") & " : E-mail cancelled for message with ID " &
                            strMessageID, "ERR")
        End If
        If e.Error IsNot Nothing Then
            Trace.WriteLine(DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") & " : Failed to send e-mail with ID " &
                            strMessageID & ", " & e.Error.ToString(), "ERR")
            'E-mail error - update table
            mobjContainer.UpdateUnsentMail(CInt(strMessageID))
        Else
            'E-mail success - delete record from table
            mobjContainer.DeleteUnsentMailItem(CInt(strMessageID))
            Trace.WriteLineIf(mobjLogTrace.LogEvents = True And mobjLogTrace.LogDetail >= 4, DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") &
                              " : E-mail with ID " & strMessageID & " successfully sent", "EVT")
        End If

    Catch objException As Exception
        Trace.WriteLine(DateTime.Now().ToString("dd/MM/yyyy HH:mm:ss.fff") & " : Failed to send e-mail with ID " &
                           strMessageID & ", " & objException.ToString(), "ERR")
    Finally
        v_objSender.Dispose()
    End Try
End Sub

【问题讨论】:

    标签: vb.net email dispose sendasync


    【解决方案1】:

    如果您创建了一个类来保存 intID 和 v_objMessage 并将其作为第二个参数传递给 objClient.SendAsync() 调用,您将可以访问 SendCompletedCallback() 子中的 ID 和消息。然后,您可以在 finally 块中的消息上调用 .Dispose。

    【讨论】:

    • 这似乎有效,谢谢。只是为了检查我的理解,当一个对象通过 ByVal 时,垃圾收集将处理最初创建的对象的任何痕迹。即objects的值传出去了,原来的object还保留吗?
    • @coderX 我的理解是,当没有对对象的引用时,GC会释放内存。在这种情况下,当您离开 SendCompletedCallback() 子时,应该将对象作为垃圾回收的候选对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 2015-08-09
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多