2010-11-24 8 views
1

Ich habe ein kleines Programm, in dem ich grundsätzlich eine E-Mail über den Yahoo SMTP Server senden kann. Mein Code:Warum wird das Sende-E-Mail-Programm eingefroren?

using System; 
using System.Data; 
using System.Configuration; 
using System.Web; 
using System.Net; 
using System.Net.Mail; 
using System.Drawing; 
using System.IO; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 

       try 
       { 

        MailMessage message = new MailMessage(); 
        message.From = new MailAddress("[email protected]"); 
        message.To.Add("[email protected]"); 
        message.Subject = "afdasdfasfg"; 
        message.Body = "Hgfk4564267862738I"; 
        message.IsBodyHtml = true; 
        message.Priority = MailPriority.High; 
        SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com"); 
        sC.Port = 587; 
        sC.Credentials = new NetworkCredential("myid", "mypassword"); 
        //sC.EnableSsl = true; 
        sC.Send(message); 
        MessageBox .Show ("Mail Send Successfully"); 

       } 
       catch (Exception ex) 
       { 
        MessageBox .Show (ex + "Mail Sending Fail's") ; 

       } 
      } 

     } 
    } 

Die seltsame Sache ist, dass es für die erste Woche funktionierte. Ich könnte Nachrichten ohne Probleme senden. Erst gestern fängt das Programm einfach an zu frieren und antwortet nicht (ich habe den Code nicht geändert). Warum ist das passiert? Wie kann ich mein Programm verbessern?

Edit: @Andreas Niedermair Gerade jetzt habe ich versucht, einfach das Programm und ließ es für eine ganze Minute dann ein Fehler zeigte: ContextSwitchDeadlock erkannt wurde Nachricht: Die CLR ist es nicht gelungen von COM Kontext für den Übergang 0x21eb78 zu COM Kontext 0x21ece8 für 60 Sekunden. Der Thread, der den Zielkontext/das Zielobjekt besitzt, führt höchstwahrscheinlich entweder eine nicht pumpende Wartezeit durch oder verarbeitet eine sehr lange laufende Operation, ohne Windows-Nachrichten zu pumpen. Diese Situation wirkt sich im Allgemeinen negativ auf die Leistung aus und kann sogar dazu führen, dass die Anwendung nicht mehr reagiert oder sich die Speicherbelegung im Laufe der Zeit ständig erhöht. Um dieses Problem zu vermeiden, sollten alle STA-Threads (single threaded apartments) Pump-Warte-Primitive (wie CoWaitForMultipleHandles) verwenden und während langer Betriebsvorgänge routinemäßig Nachrichten pumpen.

Danke für Ihre Hilfe!

+1

Haben Sie versucht, es zu debuggen, um zu sehen, wo es hängt? – Bernard

+0

mit welchem ​​.net Framework arbeiten Sie? –

Antwort

1

wird Ihre catch jemals erreicht?

Ich nehme an, dass Sie nicht geduldig genug sind, um den Standardwert der Timeout Eigenschaft (100seconds) zu erreichen ... Sie könnten den Wert verringern, um einen früheren Abschluss zu erhalten.

Solange Sie nicht mit einem asynchronen Muster arbeiten, wird Ihr UI-Thread trotzdem blockiert. eine Alternative wäre, die SendAsync Methode zu verwenden (es gibt Beispielimplementierungen in den msdn-Einträgen für die spezifischen Methoden).

Edit:
wie der Autor eine mögliche fu ** ed Port erwähnt: ja, könnte es sein. aber Sie müssten die specification paper lesen, das sagt uns:

  • SMTP-Server: plus.smtp.mail.yahoo.com
  • SSL verwenden
  • Hafen: 465
  • Authentifizierung verwenden
  • Kontoname/Anmeldename: Ihre Yahoo! Mail-ID (Ihre E-Mail-Adresse ohne "@ yahoo.com", z. B. "testing80")
  • E-Mail-Adresse: Your Yahoo! E-Mail-Adresse (z. B. [email protected])
  • Kennwort: Ihre Yahoo! Mail password
  • [...] versuche die SMTP-Portnummer auf 587 zu setzen, wenn ich E-Mails über den SMTP-Server von Yahoo! sende.

aber auch wenn Sie die Spezifikationen erfüllen: Sie wirklich für die Asynchron-Muster gehen sollte :)

Edit: die erwähnte Ausnahme von COM bezieht ...ein bisschen googeln, und ich habe this gefunden:

Was wohl passiert, dass Sie ein COM-Objekt in einem Formular haben und Sie arbeiten auf dem UI-Thread tun. Wenn Ihre UI für> 60 Sekunden von der Verarbeitung blockiert wird, kann die COM-Komponente beschweren.

Edit:

anders: Haben Sie irgendetwas in dem Ausnahmen-Dialog von Visual Studio ändern? dann könnte das dein solution sein, oder this one (mit ein paar grundlegenden Erklärungen) ...

+0

Könnten Sie mir das bitte im Code erklären? –

+0

@Omar: überarbeitete Antwort –

+0

@Andreas Niedermair Denken Sie, dass es ein Problem mit dem Hafen geben könnte? –

0

Laut Andreas Niedermair bearbeiten Sie das Problem, dass Sie den Haupt-Thread für mehr als 60 Sekunden blockieren. Am besten ist es, wenn Sie diese Operation auf einen Hintergrund-Thread anwenden.

using System; 
using System.ComponentModel; 
using System.Net; 
using System.Net.Mail; 
using System.Windows.Forms; 

namespace Sandbox_Form 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      bw = new BackgroundWorker(); 
      bw.DoWork +=new DoWorkEventHandler(bw_DoWork); 
      bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     } 

     void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if(e.Error != null) 
       MessageBox.Show(e.Error.ToString() + "Mail Sending Fail's") ; 
      else 
       MessageBox.Show("Mail Send Successfully"); 
     } 

     BackgroundWorker bw; 

     void bw_DoWork(object sender, DoWorkEventArgs e) 
     { 
      using(MailMessage message = new MailMessage()) 
      { 
       message.From = new MailAddress("[email protected]"); 
       message.To.Add("[email protected]"); 
       message.Subject = "afdasdfasfg"; 
       message.Body = "Hgfk4564267862738I"; 
       message.IsBodyHtml = true; 
       message.Priority = MailPriority.High; 
       using(SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com")) 
       { 
        sC.Port = 587; 
        sC.Credentials = new NetworkCredential("myid", "mypassword"); 
        //sC.EnableSsl = true; 
        sC.Send(message); 
       } 
      } 
     } 
     private void button1_Click(object sender, EventArgs e) 
     { 
      bw.RunWorkerAsync(); 
     } 
    } 

} 

EDIT:

pro Andreas Niedermair Vorschlag, hier eine Version anstelle von der Asynchron-Methode.

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 

      MailMessage message = new MailMessage(); 
      message.From = new MailAddress("[email protected]"); 
      message.To.Add("[email protected]"); 
      message.Subject = "afdasdfasfg"; 
      message.Body = "Hgfk4564267862738I"; 
      message.IsBodyHtml = true; 
      message.Priority = MailPriority.High; 
      SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com"); 
      sC.Port = 587; 
      sC.Credentials = new NetworkCredential("myid", "mypassword"); 
      //sC.EnableSsl = true; 
      //sC.Send(message); 
      sC.SendCompleted += new SendCompletedEventHandler(sC_SendCompleted); 
      sC.SendAsync(message, null); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex + "Mail Sending Fail's"); 
     } 

    } 

    void sC_SendCompleted(object sender, AsyncCompletedEventArgs e) 
    { 
     if(e.Error != null) 
      MessageBox.Show(ex + "Mail Sending Fail's"); 
     else 
      MessageBox.Show("Mail Send Successfully"); 
    } 
} 
+0

musst du wirklich einen neuen backroundworker-thread erstellen? warum nicht die 'SendAsync'-Methode mit Callback verwenden? –

+0

Ich kannte die Sendeklasse nicht, aber das würde genauso gut funktionieren. Wird ein Beispiel hinzufügen. –

+2

@Andreas Niedermair, Ein Vorteil beim Erstellen eines separaten Hintergrund-Worker-Threads besteht darin, dass Sie die Objekte sofort nach ihrer Fertigstellung entsorgen können, anstatt darauf zu warten, dass der GC sie ausführt (sowohl MailMessage als auch 'StmpClient' implement' IDisposeable'). –

Verwandte Themen