Jestem trochę zakłopotany tym, jak zarządzać SmtpClient teraz, gdy jest on jednorazowy, zwłaszcza jeśli wykonuję połączenia za pomocą SendAsync. Przypuszczalnie nie powinienem wywoływać Dispose, dopóki SendAsync nie zakończy się. Ale czy powinienem to kiedykolwiek nazwać (np. Używając „używając”). Scenariusz to usługa WCF, która okresowo wysyła wiadomości e-mail, gdy wykonywane są połączenia. Większość obliczeń jest szybka, ale wysłanie wiadomości e-mail może zająć około sekundy, więc preferowany byłby Async.
Czy powinienem tworzyć nowego SmtpClient za każdym razem, gdy wysyłam pocztę? Czy powinienem utworzyć jeden dla całego programu WCF? Wsparcie!
Aktualizacja Jeśli ma to znaczenie, każdy e-mail jest zawsze dostosowany do użytkownika. Usługa WCF jest hostowana na platformie Azure, a Gmail jest używany jako poczta.
źródło
Odpowiedzi:
Uwaga: .NET 4.5 SmtpClient implementuje
async awaitable
metodęSendMailAsync
. W przypadku niższych wersji użyjSendAsync
zgodnie z opisem poniżej.Zawsze powinieneś
IDisposable
jak najszybciej pozbywać się instancji. W przypadku wywołań asynchronicznych jest to wywołanie zwrotne po wysłaniu wiadomości.To trochę denerwujące, że
SendAsync
nie przyjmuje oddzwonienia.źródło
await
był dostępny. Jest to tradycyjne wywołanie zwrotne z obsługą zdarzeń.await
powinien być używany, jeśli używasz nowszegoSendMailAsync
.null
drugi parametr doSendAsync(...)
?Pierwotne pytanie dotyczyło platformy .NET 4, ale jeśli to pomaga, od wersji .NET 4.5 SmtpClient implementuje metodę async awaitable
SendMailAsync
.W rezultacie asynchroniczne wysyłanie wiadomości e-mail wygląda następująco:
Lepiej unikać używania metody SendAsync.
źródło
MailMessage
należy również usunąć.Ogólnie rzecz biorąc, obiekty IDisposable powinny zostać usunięte tak szybko, jak to możliwe; implementacja IDisposable na obiekcie ma na celu zakomunikowanie faktu, że dana klasa zawiera kosztowne zasoby, które powinny być deterministycznie uwalniane. Jeśli jednak tworzenie tych zasobów jest kosztowne i musisz skonstruować wiele z tych obiektów, może być lepiej (z punktu widzenia wydajności) zachować jedną instancję w pamięci i użyć jej ponownie. Jest tylko jeden sposób, aby dowiedzieć się, czy to robi jakąkolwiek różnicę: profiluj to!
Re: disposing and Async:
using
oczywiście nie możesz użyć . Zamiast tego zazwyczaj usuwasz obiekt w zdarzeniu SendCompleted:źródło
Ok, stare pytanie, które znam. Ale sam się na to natknąłem, gdy potrzebowałem zaimplementować coś podobnego. Chciałem tylko udostępnić jakiś kod.
Iteruję przez kilka SmtpClients, aby wysłać kilka wiadomości e-mail asynchronicznie. Moje rozwiązanie jest podobne do TheCodeKing, ale zamiast tego usuwam obiekt wywołania zwrotnego. Przekazuję również MailMessage jako userToken, aby uzyskać go w zdarzeniu SendCompleted, więc mogę również wywołać dispose. Lubię to:
źródło
4.3.2 The maximum number of concurrent connections has exceeded a limit, closing trasmission channel
. Zamiast tego spróbuj użyć tylko jednego wystąpieniaSmtpClient
Możesz zobaczyć, dlaczego pozbycie się SmtpClient jest szczególnie ważne, po następującym komentarzu:
W moim scenariuszu wysyłania wielu wiadomości za pomocą Gmaila bez usuwania klienta otrzymywałem:
źródło