2010-07-19 4 views
2

Я создаю почтовое программное обеспечение, которое отправляет электронное письмо на некоторые учетные записи. Я хочу добавлять текст каждый раз, когда новое письмо отправляется или проваливается. Но текстовое поле показывает мне отчет после отправки всех писем. Если список toList очень велик, как 30+ писем, экран приложения становится белым, и после отправки всех писем GUI возвращается с обновленным OutPutTextBox. Вот код внутри метода SendButton_ClickОбновление текстового поля асинхронно

foreach (String to in toList) 
      { 
       bool hasSent = SendMail(from, "password", to, SubjectTextBox.Text, BodyTextBox.Text); 

       if (hasSent) 
       { 
        OutPutTextBox.appendText("Sent to: " + to); 
       } 
       else 
       { 
        OutPutTextBox.appendText("Failed to: " + to); 
       } 
      } 

ответ

5

То, что вы действительно хотите сделать, это вызвать SendMail асинхронно. В .NET 4.0 есть несколько способов сделать это. Я рекомендую начать Task объект в вашем foreach цикла, и планирование задач продолжения для каждого из них в поток пользовательского интерфейса:

string subject = SubjectTextBox.Text; 
string body = BodyTextBox.Text; 
var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
List<Task> mails = new List<Task>(); 
foreach (string to in toList) 
{ 
    string target = to; 
    var t = Task.Factory.StartNew(() => SendMail(from, "password", target, subject, body)) 
     .ContinueWith(task => 
     { 
     if (task.Result) 
     { 
      OutPutTextBox.appendText("Sent to: " + to); 
     } 
     else 
     { 
      OutPutTextBox.appendText("Failed to: " + to); 
     } 
     }, ui); 
    mails.Add(t); 
} 

Task.ContinueWhenAll(mails.ToArray(), _ => { /* do something */ }); 

(синтаксис может быть немного не, я не скомпилировать).

+0

любой фрагмент кода? – coure2011

+0

См. Обновленный ответ. –

+0

пара проблем с этим решением. Сначала он отправляет все электронные письма на тот же адрес. Во-вторых, как узнать, что все Задачи закончены? – coure2011

3

Это похоже на работу (предполагается, что приложение WinForm):

namespace WindowsFormsApplication5 
{ 
    using System; 
    using System.Threading; 
    using System.Windows.Forms; 

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

     TextBox OutPutTextBox = new TextBox(); 

     /// <summary> 
     /// Represents Send Mail information. 
     /// </summary> 
     class MailInfo 
     { 
      public string from; 
      public string password; 
      public string to; 
      public string subject; 
      public string body; 
     } 

     void ProcessToDoList(string[] toList) 
     { 
      foreach (var to in toList) 
      { 
       MailInfo info = new MailInfo(); 
       info.from = "xx"; //TODO. 
       info.password = "yy"; //TODO. 
       info.to = "zz"; //TODO. 
       info.subject = "aa"; //TODO. 
       info.body = "bb"; //TODO. 
       ThreadPool.QueueUserWorkItem(this.SendMail, info); 
      } 
     } 

     /// <summary> 
     /// Send mail. 
     /// NOTE: this occurs on a separate, non-UI thread. 
     /// </summary> 
     /// <param name="o">Send mail information.</param> 
     void SendMail(object o) 
     { 
      MailInfo info = (MailInfo)o; 
      bool hasSent = false; 

      //TODO: put your SendMail implementation here. Set hasSent field. 
      // 

      // Now test result and append text. 
      // 

      if (hasSent) 
      { 
       this.AppendText("Sent to: " + info.to); 
      } 
      else 
      { 
       this.AppendText("Failed to: " + info.to); 
      } 
     } 

     /// <summary> 
     /// Appends the specified text to the TextBox control. 
     /// NOTE: this can be called from any thread. 
     /// </summary> 
     /// <param name="text">The text to append.</param> 
     void AppendText(string text) 
     { 
      if (this.InvokeRequired) 
      { 
       this.BeginInvoke((Action)delegate { this.AppendText(text); }); 
       return; 
      } 

      OutPutTextBox.AppendText(text); 
     } 
    } 
} 
Смежные вопросы