.NET SMTP SendAsync с AlternateViews создает удаленное исключение

Я пытаюсь отправлять электронные письма асинхронно, и это работает нормально, пока к электронному письму не прикреплено AlternateView. Когда есть альтернативный вид, я получаю следующую ошибку:

Cannot access a disposed object. Object name: 'System.Net.Mail.AlternateView'
System.Net.Mail.SmtpException: Failure sending mail. ---> System.ObjectDisposedException: Cannot access a disposed object.

Object name: 'System.Net.Mail.AlternateView'.
   at System.Net.Mail.AlternateView.get_LinkedResources()
   at System.Net.Mail.MailMessage.SetContent()
   at System.Net.Mail.MailMessage.BeginSend(BaseWriter writer, Boolean sendEnvelope, AsyncCallback callback, Object state)
   at System.Net.Mail.SmtpClient.SendMailCallback(IAsyncResult result)

Вот пример кода:

Dim msg As New System.Net.Mail.MailMessage
msg.From = New System.Net.Mail.MailAddress("[email protected]", "My Name")
msg.Subject = "email subject goes here"

'add the message bodies to the mail message
Dim hAV As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(textBody.ToString, Nothing, "text/plain")
hAV.TransferEncoding = Net.Mime.TransferEncoding.QuotedPrintable
msg.AlternateViews.Add(hAV)

Dim tAV As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(htmlBody.ToString, Nothing, "text/html")
tAV.TransferEncoding = Net.Mime.TransferEncoding.QuotedPrintable
msg.AlternateViews.Add(tAV)

Dim userState As Object = msg
Dim smtp As New System.Net.Mail.SmtpClient("emailServer")

'wire up the event for when the Async send is completed
 AddHandler smtp.SendCompleted, AddressOf SmtpClient_OnCompleted

 Try
     smtp.SendAsync(msg, userState)
 Catch '.... perform exception handling, etc...
 End Try

И Обратный звонок.....

 Public Sub SmtpClient_OnCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
    If e.Cancelled Then
      'Log the cancelled error
    End If
    If Not IsNothing(e.Error) Then
        'Log a real error....
        ' this is where the error is getting picked up
    End If

    'dispose the message
    Dim msg As System.Net.Mail.MailMessage = DirectCast(e.UserState, System.Net.Mail.MailMessage)
    msg.Dispose()

End Sub

person hacker    schedule 22.04.2009    source источник


Ответы (3)


Причина, по которой это не работает, заключается в том, что ваш обработчик OnCompleted вызывается, когда метод SendAsync() завершается, но, по-видимому, это происходит до того, как SmtpClient физически завершил отправку электронной почты по сети (хотя это произойдет только при доставке по сети, доставка файлов по существу синхронна с SendAsync()).

Это почти похоже на ошибку в SmtpClient, потому что OnCompleted действительно должен вызываться только тогда, когда сообщение действительно отправлено.

person Jeremy Wiebe    schedule 23.04.2009
comment
Я отправил заявку в Microsoft. Посмотрим, принесет ли это мне что-нибудь. - person hacker; 24.04.2009
comment
Microsoft ответила и указала, что они смогли заставить его работать нормально без ошибок. У меня не было возможности вернуться к этому приложению, чтобы повторно применить асинхронную отправку электронной почты и протестировать его. - person hacker; 05.05.2009

У меня была очень похожая проблема. То же сообщение об ошибке, но немного другая структура кода. В моем случае я избавлялся от объекта mailmessage внутри основной функции. К моменту запуска события OnCompleted объект уже исчез.

Посмотрите на свой код после SendAsync, чтобы узнать, освобождаете ли вы объект mailmessage. Например, если вы создаете его внутри оператора using, он будет освобожден до запуска асинхронного события.

person NotMe    schedule 25.04.2009
comment
Я проверил это, потому что изначально у меня было MailMessage, удаляемое в блоке finally. К сожалению, AlternateViews не удаляются (сейчас вообще), а MailMessage удаляется в конце блока OnCompleted. Ошибка возникает еще до того, как она доходит до вызова dispose MailMessage. Одна вещь, о которой я думаю, это то, что GC собирает объект слишком быстро... хотя не уверен, что это возможно. - person hacker; 25.04.2009

Вы должны поместить свои димы на уровень класса, если хотите получить к ним доступ в своем обратном вызове.

private msg As System.Net.Mail.MailMessage
private hAV As System.Net.Mail.AlternateView 

private sub yoursub
  msg = new System.Net.Mail.MailMessage(..
  hAV = new ...
end sub

Я предполагаю, что AlternateViews.Add просто добавляет ссылку на hAV, объект msg должен удаляться, в то время как hAV автоматически удаляется сборщиком мусора.

Ваше здоровье

person Evolved    schedule 27.07.2011