2009-04-22 8 views
1

J'essaie d'envoyer des courriels de façon asynchrone et cela fonctionne très bien tant qu'il n'y a pas un AlternateView attaché à l'e-mail. Quand il y a un autre point de vue, je reçois l'erreur suivante:.NET SMTP SendAsync avec AlternateViews throws disposition exception

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) 

Voici quelques exemples de code:

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 

Et le rappel .....

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 

Répondre

2

La raison cela ne fonctionne pas parce que votre gestionnaire OnCompleted est appelé lorsque la méthode SendAsync() est terminée, mais cela semble être avant que SmtpClient ait fini d'envoyer physiquement l'email sur le réseau (ceci Cependant, les livraisons de fichiers sont essentiellement synchrones avec SendAsync()). Cela ressemble presque à un bug dans le SmtpClient car OnCompleted ne devrait vraiment être appelé que lorsque le message a vraiment été envoyé.

+0

J'ai envoyé un soumission à Microsoft. Nous verrons si ça m'amène n'importe où. – hacker

+0

Microsoft a répondu et a indiqué qu'ils étaient en mesure de le faire fonctionner correctement sans erreur. Je n'ai pas eu l'occasion de revenir à cette application afin de réappliquer l'envoi de courrier électronique de manière asynchrone et de le tester. – hacker

0

J'ai eu un problème très similaire. Même message d'erreur, mais structure de code légèrement différente. Dans mon cas, je disposais de l'objet mailmessage dans la fonction principale. Au moment où l'événement OnCompleted s'est déroulé, l'objet était déjà parti.

Regardez votre code après SendAsync pour voir si vous libérez l'objet mailmessage. Par exemple, si vous le créez dans une instruction using, il sera libéré avant l'exécution de l'événement asynchrone.

+0

J'ai vérifié cela parce qu'au début, j'avais le MailMessage disposé dans le bloc finally. Malheureusement, les AlternateViews ne sont pas éliminés (du tout maintenant) et le MailMessage est éliminé à la fin du bloc OnCompleted. L'erreur se produit avant même qu'il ne parvienne à l'appel de distribution MailMessage. Une chose à laquelle je pense, c'est que le GC collecte l'objet trop rapidement ... je ne sais pas si c'est possible. – hacker

0

Vous devriez mettre vos dims au niveau de la classe si vous voulez y accéder dans votre callback.

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 

Je pense que AlternateViews.Add ne fait qu'ajouter une référence de VHA, les besoins de l'objet msg disposent alors que le VHA est disposé automatiquement par le GC ..

Vive