2015-01-22 2 views
2

여기 또는 MSDN에서 결정적인 대답을 찾을 수 없었습니다. 다음 코드를 사용할 때 비동기 메일을 보낸 후 메시지를 처리하려고하면 이 표시됩니다. System.ObjectDisposedException : 폐기 된 개체에 액세스 할 수 없습니다. 이것은 Microsoft 예제에서 처분을 제안하는 경우입니다. 메시지가 범위를 벗어 났으므로 콜백에 메시지를 처리 ​​할 수 ​​없습니다. 모듈 수준의 메일 메시지를 사용해 보았지만 동일한 결과가 나타납니다. 메시지를 처리하지 않으면 모든 것이 잘 작동하지만 이것은 좋은 습관이 아닙니다. 조언을 메일 메시지를 처분하는 가장 좋은 장소에 주시기 바랍니다.SendAsync를 사용할 때 VB에서 System.Net.Mail.MailMessage를 어떻게 처리합니까?

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 

답변

0

당신이 intID하고 v_objMessage 모두를 개최하는 클래스를 생성하고 ID와 SendCompletedCallback의 메시지 모두에 액세스 할 수있는 것) 호출하여 objClient.SendAsync (두 번째 매개 변수로이 통과하는 경우() 보결. 그런 다음 Finally 블록의 메시지에서 .Dispose를 호출 할 수 있습니다.

+0

고마워요. 내 이해를 확인하기 위해, 객체가 전달 될 때 ByVal은 가비지 컬렉션에서 원래 생성 된 객체의 흔적을 처리합니다. 즉, 객체 값이 전달되면 원래 객체가 남아 있습니까? – coderX

+0

@ cododer 제 생각에 GC는 객체에 대한 참조가 없을 때 메모리를 해제합니다. 이 경우 SendCompletedCallback() 서브 루틴을 떠날 때 가비지 콜렉션의 후보로 객체를 남겨 두어야합니다. – theduck

관련 문제