我遇到了问题,我正在尝试使用这样的结构发送邮件:
private void SendMail()
{
var client = new SmtpClient("smtp.gmail.com", 587)
{
Credentials = new NetworkCredential("mymail@mail.com", "mypassword"),
EnableSsl = true
};
client.Send("mymail@mail.com", "AdressClient@mail.com", "Subject", "Body");
}
嗯,这个结构运行得很好,但是导致主程序滞后,因此我想在另一个Thread中执行SendMail函数,如下所示:
private void ButtonTestSendMail_Click(object sender, EventArgs e)
{
//THREAD
Thread ThreadSendEmail = new Thread(new ThreadStart(this.SendMail));
ThreadSendEmail .IsBackground = true;
ThreadSendEmail .Start();
}
private void SendMail()
{
var client = new SmtpClient("smtp.gmail.com", 587)
{
Credentials = new NetworkCredential("mymail@mail.com", "mypassword"),
EnableSsl = true
};
client.Send("mymail@mail.com", "AdressClient@mail.com", "Subject", "Body");
}
此时我注意到我需要更改邮件的参数,例如AdressClient@mail.com,Suject和Body。
但我不知道如何:/
如何编写接受参数的线程,如下所示:
private void ButtonTestSendMail_Click(object sender, EventArgs e)
{
string Body = "BodyTest";
string AdressMail = "AdressMail@test.com";
string Subject = "SubjectTest";
//THREAD
Thread ThreadSendEmail = new Thread(new ThreadStart(this.SendMail(Body,AdressMail,Subject));
ThreadSendEmail .IsBackground = true;
ThreadSendEmail .Start();
}
private void SendMail(string Body, string Adress, string Subject)
{
var client = new SmtpClient("smtp.gmail.com", 587)
{
Credentials = new NetworkCredential("mymail@mail.com", "mypassword"),
EnableSsl = true
};
client.Send("mymail@mail.com", Adress, Subject, Body);
}
我尝试了但是没有用,我有一个预期的MethodName,并且有一条通知表明ERROR在这一行:
Thread ThreadSendEmail = new Thread(new ThreadStart(this.SendMail(Body,AdressMail,Subject));
如何编写接受参数的线程? 谢谢你的帮助! 最诚挚的问候!
答案 0 :(得分:2)
你快到了:
Thread ThreadSendEmail = new Thread(() => this.SendMail(Body,AdressMail,Subject));
lambda成功了。你不能直接调用SendMail,你想把它作为一个无意义的函数传递。
请注意,如果您的ASP.NET进程回收(可能是因为您正在部署),该线程将被粗暴地中止。邮件将丢失。
答案 1 :(得分:2)
如果您只需要异步发送邮件,则可以使用 SmtpClient.SendAsync 方法,并且不会阻止您的调用线程(http://msdn.microsoft.com/en-us/library/x5x13z6h.aspx)。
但是如果你真的想要一个新线程来做这项工作,你需要创建一个包含你的参数值的类,并使用 ParameterizedThreadStart 委托来实现它。 这是一个带有一个样本的SO条目: ThreadStart with parameters
答案 2 :(得分:1)
显式创建自己的线程通常没有必要,有时也是一个坏主意。相反,您可以利用.NET ThreadPool启动现有但非主线程的工作。例如:
ThreadPool.QueueUserWorkItem(state => { /* threadpool work */ }, null);
无论你走到哪里,在另一个线程上工作都可能是危险的,因为如果抛出任何异常(并且没有被捕获),你的应用程序将会终止。
此外,Thread.IsBackground = true
的唯一效果是不阻止您的应用在运行时退出。如果您的目的是更改线程优先级,则应设置不同的属性。
如果您使用的是.NET 4.0,则可以使用更高级别的抽象来帮助您处理异常:
Task task = Task.Factory.StartNew(() => { /* threadpool work */ });
稍后,如果在任务中抛出异常,您可以观察它并根据需要使用Task对象上的各种属性和方法做出反应。在.NET 4.0上,如果你不观察异常但只是让任务得到GC,那么它也会使你的应用程序崩溃(尽管在非确定性的时候,每当Finalizer运行时) 。在.NET 4.5上,您的应用程序在此方案中不崩溃。
最后,如果您使用的是.NET 4.5,则可以更短:
Task task = Task.Run(() => { /* threadpool work */ });
答案 3 :(得分:0)
Thread.Start()
方法有一个重载,第二个object
参数传递给线程方法 - 所以你可以这样做:
Thread ThreadSendEmail = new Thread(new ThreadStart(this.SendMail));
ThreadSendEmail.IsBackground = true;
ThreadSendEmail.Start("Body test");
. . . .
private void SendMail(object data)
{
string body = (string)data;
. . .
}
如果你想/需要传递更多参数将它们捆绑在一个对象中,并传递该对象。
除了创建一个线程,您可以使用线程池,它可以更好地扩展,并且更容易使用,只需一行代码:
ThreadPool.QueueUserWorkItem(new WaitCallback(SemdMail), "Body test");
P.S。这是'旧式'解决方案,'现代'解决方案是使用lambdas - 请参阅@usr答案。