我正在创建一个电子邮件软件,可以向某些帐户发送电子邮件。我想在每次发送或发送新电子邮件时附加文本。但是文本框在发送所有电子邮件后显示我的报告。如果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);
}
}
答案 0 :(得分:5)
您实际想要做的是异步调用SendMail
。在.NET 4.0中有几种方法可以做到这一点。我建议在Task
循环中启动foreach
对象,并为UI线程安排每个对象的任务延续:
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 */ });
(语法可能稍微关闭;我没有编译它。)
答案 1 :(得分: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 );
}
}
}