Versenden von E-Mails in separaten threads mit QueueUserWorkItem

Ich habe eine Konsole-Anwendung, die sendet maßgeschneiderten E-Mails (mit Anlagen) an verschiedene Empfänger und ich möchte Ihnen gleichzeitig. Ich brauche die Erstellung von separaten SmtpClients um dies zu erreichen, so bin ich mit QueueUserWorkItem zu erstellen, die E-Mails und senden Sie Sie in separate threads.

Snippet

var events = new Dictionary<Guid, AutoResetEvent>();
foreach (...)
{
    ThreadPool.QueueUserWorkItem(delegate
    {
        var id = Guid.NewGuid();
        events.Add(id, new AutoResetEvent(false));
        var alert = //create custom class which internally creates SmtpClient & Mail Message
        alert.Send();
        events[id].Set();
    });   
}
//wait for all emails to signal
WaitHandle.WaitAll(events.Values.ToArray());

Habe ich bemerkt (nur zeitweise), dass manchmal nicht alle emails kommen in die bestimmte Postfächer mit dem obigen code. Ich hätte gedacht, dass mit Send über SendAsync würde bedeuten, die E-Mail wurde geschickt von der Anwendung. Doch indem Sie die folgende Zeile des Codes nach der WaitHandle.WaitAll Linie:

System.Threading.Thread.Sleep(5000);

Scheint zu funktionieren. Mein denken ist, aus welchem Grund auch immer, einige E-Mails noch nicht gesendet wurde (auch nach der Send Methode ausgeführt wurde). Geben Sie die zusätzlichen 5 Sekunden zu geben scheint die Anwendung genug Zeit, um fertig zu stellen.

Ist dies vielleicht ein Problem mit der Art und Weise, warte ich auf die E-Mails zu senden? Oder ist das ein Problem mit dem eigentlichen "Send" - Methode? Hat die E-Mail definitiv versendet wurden, von der app einmal passieren wir diese Linie?

Irgendwelche Gedanken die Idee zu diesem wäre toll, kann nicht ganz scheinen, um meine finger auf die eigentliche Ursache.

Update

Verlangt wie hier ist der SMTP-code:

SmtpClient client = new SmtpClient("Host");
FieldInfo transport = client.GetType().GetField("transport", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo authModules = transport.GetValue(client).GetType()
    .GetField("authenticationModules", BindingFlags.NonPublic | BindingFlags.Instance);
Array modulesArray = authModules.GetValue(transport.GetValue(client)) as Array;
modulesArray.SetValue(modulesArray.GetValue(2), 0);
modulesArray.SetValue(modulesArray.GetValue(2), 1);
modulesArray.SetValue(modulesArray.GetValue(2), 3);
try
{
    //create mail message
    ...
    emailClient.Send(emailAlert);
}
catch (Exception ex)
{
    //log exception
}
finally
{
    emailAlert.Dispose();
}
  • Können Sie erstellen, die eine kurze, aber komplette, Programm das stellt das problem?
  • Ich werde versuchen die vorgeschlagenen Lösungen dann posten, wenn noch nichts.
  • Können Sie Ihre SMTP-code?
  • Warum kannst du nicht verwenden SendAsync und einfach Prozess der Abschluss-Ereignisse, so dass Sie wissen, ob alle E-Mails die gesendet wurden?
  • Ich glaube, du verpasst einige der code. Ich sehe keinen Anruf zu senden.
  • Ich möchte zum senden der Benachrichtigungen so schnell wie möglich und Sie können ausgelöst werden, ziemlich viel 1 nach dem anderen, man darf nur senden, 1 asychronously auf jeden 1 mal, das war meine ursprüngliche Idee.
  • Sie nicht ernsthaft erwarten, dass ich post meine vollständigen code der Anwendung haben Sie? Sicherlich wird der code geschrieben in meinem Fragen & Antworten ist genug für Sie zu gehen?
  • Nicht die volle Anwendung, nur senden E-Mail-Prozess, wenn es möglich ist wie diese stackoverflow.com/a/1687178/206730 ich möchte vergleichen, Beispiele, finden, klarer, eleganter code

InformationsquelleAutor James | 2010-01-08
Schreibe einen Kommentar