1

問題があります。次のような構造を使用してメールを送信しようとしています。

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

この構造は問題なく動作しますが、メイン プログラムで遅延が発生するため、次のように別のスレッドで 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、件名、本文など、メールのパラメーターを変更する必要があることに気付きました。

しかし、方法がわかりません:/

次のようなパラメーターを受け入れるスレッドを作成するにはどうすればよいですか。

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 Expected があり、エラーが次の行にあるという通知があります:

Thread ThreadSendEmail = new Thread(new ThreadStart(this.SendMail(Body,AdressMail,Subject));

パラメータを受け入れるスレッドを作成するにはどうすればよいですか? ご協力ありがとう御座います!よろしくお願いします!

4

4 に答える 4

2

あなたはほとんどそこにいます:

Thread ThreadSendEmail = new Thread(() => this.SendMail(Body,AdressMail,Subject));

ラムダはトリックを行います。SendMailを直接呼び出すことはできません。呼び出されていない関数として、SendMailを渡します。

ASP.NETプロセスがリサイクルされると(おそらくデプロイしているため)、スレッドが無礼に中止されることに注意してください。その後、メールは失われます。

于 2013-03-02T22:20:24.227 に答える
2

メール メッセージを非同期的に送信するだけでよい場合は、SmtpClient.SendAsyncメソッドを使用できます。呼び出し元のスレッドはブロックされません ( http://msdn.microsoft.com/en-us/library/x5x13z6h.aspx ) 。 .

ただし、本当に新しいスレッドでジョブを実行したい場合は、パラメーター値を含むクラスを作成し、ParameterizedThreadStartデリゲートを使用してインスタンス化する必要があります。1 つのサンプルを含む SO エントリを次に示します。 ThreadStart with parameters

于 2013-03-02T22:27:50.580 に答える
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するだけの場合、アプリもクラッシュします(ただし、ファイナライザーが実行されるたびに、非決定的な時間になります)。.NET 4.5では、このシナリオでアプリがクラッシュすることはありません。

最後に、.NET 4.5を使用している場合は、さらに短くすることができます。

Task task = Task.Run(() => { /* threadpool work */ });
于 2013-03-02T22:31:57.977 に答える
0

このThread.Start()メソッドには、スレッドメソッドに渡される2番目のパラメーターを持つオーバーロードがあり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;
  . . . 
}

より多くのパラメーターを渡す必要がある場合は、それらをオブジェクトにバンドルし、そのオブジェクトを渡します。

スレッドを作成する代わりに、スレッドプールを使用できます。これにより、拡張性が向上し、使いやすくなります。コードは1行だけです。

ThreadPool.QueueUserWorkItem(new WaitCallback(SemdMail), "Body test");

PSこれは「古いスタイル」のソリューションです。「現代的な」ソリューションはラムダを使用することです。@usrの回答を参照してください。

于 2013-03-02T22:21:23.627 に答える