2008-12-23 22 views
21

Ich versuche, einen Benachrichtigungsdienst (für völlig legitime Nicht-Spam-Zwecke) in .NET mit SmtpClient zu schreiben. Anfangs habe ich einfach jede Nachricht durchgeschleift und gesendet, aber das ist langsam und ich möchte die Geschwindigkeit verbessern. Also, ich wechselte zu ‚SendAsync‘ verwenden, aber jetzt die folgenden Fehlermeldung auf dem zweiten Anruf erhalten:Warum kann SmtpClient.SendAsync nur einmal aufgerufen werden?

An asynchronous call is already in progress. 

ich diese Zeilen lesen bedeuten, dass MS System.Net.Mail verkrüppelte Massenmailer zu verhindern. Ist das richtig? Wenn ja, gibt es einen besseren Weg, dies in .NET zu tun, und trotzdem in der Lage zu sein, die Ergebnisse jeder E-Mail zu protokollieren (was für unseren Kunden wichtig ist). Wenn nicht, warum kann SendAsync nur einmal aufgerufen werden?

Antwort

35

Nach den documentation:

Nach SendAsync aufrufen, müssen Sie für die E-Mail-Übertragung zu vollständigen warten, bevor einem anderen E-Mail-Nachricht senden oder SendAsync mit senden.

Um mehrere E-Mails gleichzeitig senden zu können, benötigen Sie mehrere SmtpClient-Instanzen.

+0

Hat noch niemand einen solchen Mechanismus implementiert, um mehrere E-Mails gleichzeitig zu senden? oben auf der SMTP-Client-Klasse? klingt wie ein Problem, dem viele Leute begegnen ... irgendwie komisch, dass niemand jemals einen Rahmen dafür geschaffen hat. –

+3

@ItayLevin Ich sehe keinen Bedarf für den Versuch, die SmtpClient-Instanz wiederzuverwenden. Warum nicht einfach jede Instanz für jeden E-Mail-Sendeversuch zuweisen, wie Darin es fachmännisch erklärt hat. – Roman

+0

Dies ist ein [guter Beitrag] (http://www.codeflenzy.net/2012/01/30/how-asynchronous-is-smtpclient-sendasync/) zum Thema. –

3

Offensichtlich ist dies kein Versuch, Massenmailer zu stoppen.

Der Grund ist, dass die SmtpClient-Klasse nicht threadsicher ist. Wenn Sie mehrere E-Mails gleichzeitig senden möchten, müssen Sie einige Arbeitsthreads generieren (in .NET Framework gibt es dafür mehrere Möglichkeiten) und separate Instanzen von SmtpClient in jedem dieser Threads erstellen.

1

Sie können nur jeweils einen SMTP-Client senden. Wenn Sie mehrere Sendeaufrufe tätigen möchten, erstellen Sie mehr als einen SMTP-Client.

HTH,

Colby Afrika

3

Ich glaube, Sie die XXXAsync Klasse von Methoden falsch verstehen. Der Zweck dieser asynchronen Aufrufe besteht darin, das Programm weiterlaufen zu lassen, ohne dass die Methode die Verarbeitung beenden und als erstes zurückgeben muss. Sie können dann mit dem Ergebnis später fortfahren, indem Sie etwas wie XXXReceived Ereignis des Objekts abonnieren.

Um mehrere E-Mails gleichzeitig zu senden, können Sie mehr Thread s verwenden.

+1

Mehrere Threads, die das SendAsync aufrufen, sind genau das, was diese Ausnahme verursacht – hackerhasid

+0

@statichippo Das OP hat die Async-Version von send mail überhaupt nicht verwendet. Ich habe vorgeschlagen, mehrere Threads mit Nicht-Async-Aufruf zu verwenden. – Gant

+2

Wenn Sie Send (non-async) für mehrere Threads aufrufen, erhalten Sie eine Ausnahme. Die SmtpClient-Klasse kann nur eine Nachricht zu einem Zeitpunkt senden, unabhängig davon, wie viele Threads sie senden. Es ist ein Protokollproblem, nicht wirklich ein C# Problem ... Sie müssen warten, bis eine Nachricht gesendet wird, bevor Sie eine andere senden - unabhängig davon, ob Sie SendAsync oder Send verwenden. Es sei denn, Sie möchten mehrere SmtpClients erstellen. – hackerhasid

2

Wie von allen anderen hier bemerkt, können Sie nur jeweils eine E-Mail senden, aber die Methode zum Senden eines anderen nach dem Senden des ersten besteht darin, das .SendCompleted-Ereignis der SmtpClient-Klasse zu verarbeiten die nächste E-Mail und sende das.

Wenn Sie viele E-Mails gleichzeitig senden möchten, verwenden Sie, wie die anderen bereits sagten, mehrere SmtpClient-Objekte.

6

Sie könnten in der Lage sein, die folgenden verwenden:

ThreadPool.QueueUserWorkItem(state => client.Send(msg)); 

Diese erlauben sollten Ihre Nachrichten in der Warteschlange und als Threads verfügbar werden gesendet werden.

+5

Diese Implementierung kann immer noch eine 'System.InvalidOperationException' erzeugen, wenn von derselben 'SmtpClient'-Instanz gesendet wird. –

Verwandte Themen