如何使用消息正文作为参数发送邮件并使用线程 - C#

时间:2013-03-02 22:08:39

标签: c# multithreading smtpclient

我遇到了问题,我正在尝试使用这样的结构发送邮件:

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));

如何编写接受参数的线程? 谢谢你的帮助! 最诚挚的问候!

4 个答案:

答案 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答案。