0

作業中のアプリケーションがあり、電子メールを送信しようとすると、電子メールは正常に送信されますが、アプリケーションは閉じられるまで 50% の CPU を使用します。

問題を引き起こしている send メソッドは次のとおりです。

public void Send()
{
    if(System.String.IsNullOrEmpty(this.Server))
    {
        throw new PreferenceNotSetException("Server not set");
    }
    if(System.String.IsNullOrEmpty(this.From))
    {
        throw new PreferenceNotSetException("E-Mail address not set.");
    }
    if(System.String.IsNullOrEmpty(this.To))
    {
        throw new PreferenceNotSetException("Recipients E-Mail address not set.");
    }
    using(System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.FormattedText))
    {
        message.IsBodyHtml = true;
        System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server);
        client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
        int temp = System.Net.ServicePointManager.MaxServicePointIdleTime;
        System.Net.ServicePointManager.MaxServicePointIdleTime = 1;
        try 
        {
            client.Send(message);
        }  
        catch(System.Exception ex) 
        {
            //For debugging only.
            System.Windows.Forms.MessageBox.Show(ex.ToString());              
        }
        finally
        {
            System.Net.ServicePointManager.MaxServicePointIdleTime = temp;
            //client.Dispose(); No dispose in .Net 2.0
        }
    }
}

これを機能させるために何をすべきかわかりません。助けていただければ幸いです。

ありがとう、

4

4 に答える 4

5
      System.Net.ServicePointManager.MaxServicePointIdleTime = 1;

これが問題の原因であることはほぼ間違いありません。System.Netクラスで使用される内部タイマーに影響します。それが何をするのか正確にはわかりませんが、タイムアウトと関係があると思います。そのタイマーはスレッドプールスレッドを作成します。値を変更すると、タイマーは1秒あたり1,000のスレッドプールスレッドを作成します。明らかに値を元に戻しても、作成後のタイマーは変更されません。プロパティの通常の値は100000で、値1はおそらくテストされたことがありません。

于 2010-11-09T20:25:29.373 に答える
4

50% の CPU 使用率が安定して表示される場合、2 つの CPU コアのうちの 1 つが無限ループに陥っていることを示しているようです。ただし、投稿したメソッド本体がその無限ループの原因になることはありませんでした。問題については、コードの他の部分を調べることをお勧めします。CPU 使用率が 50% のときにアプリケーションが応答しなくなりますか?

また、なぜ System.Net.ServicePointManager.MaxServicePointIdleTime を変更するのですか? 使われているのを見たことがないので、必要なければ使わないでください。

最後に、これはスタイルに関する主観的なポイントですが、使用しているネストされた if は、代替構造よりも保守性が低く、読みにくいと主張します。個人的には、条件文を入れ子にせずに、メソッドの先頭で事前条件をチェックする方がはるかにクリーンだと思います。

public void Send()
{
    if(string.IsNullOrEmpty(this.Server))
    {
        throw new PreferenceNotSetException("Server not set");
    }

    if(string.IsNullOrEmpty(this.From))
    {
        throw new PreferenceNotSetException("E-Mail address not set.");
    }

    if(string.IsNullOrEmpty(this.To))
    {
        throw new PreferenceNotSetException("Recipients E-Mail address not set.");
    }

    using(System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.FormattedText))
                { 
                   message.IsBodyHtml = true;
                    System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server);
                    client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;

                    try 
                    {
                        client.Send(message);
                    }  
                    catch(System.Exception ex) 
                    {
                        //Put this in for debugging only.
                        System.Windows.Forms.MessageBox.Show(ex.ToString());              
                    }
    }
}
于 2010-11-09T19:57:52.153 に答える
2

これはあなたの質問に対する答えではありませんが、コードを再配置するためのはるかに単純で短い(より明確だと思います)方法のデモンストレーションにすぎません。

    public void Send()
    {
        if (String.IsNullOrEmpty(Server))
        {
           throw new PreferenceNotSetException("Server not set");
        }
        if (String.IsNullOrEmpty(From))
        {
            throw new PreferenceNotSetException("Sender's E-Mail address not set.");
        }
        if (String.IsNullOrEmpty(To))
        {
            throw new PreferenceNotSetException("Recipient's E-Mail address not set.");
        }
        using (MailMessage message = new MailMessage(From, To, Subject, FormattedText))
        {
            message.IsBodyHtml = true;
            using (SmtpClient client = new SmtpClient(Server))
            {
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                int temp = ServicePointManager.MaxServicePointIdleTime;
                ServicePointManager.MaxServicePointIdleTime = 1;
                try
                {
                    client.Send(message);
                }
                catch (Exception ex)
                {
                    //Put this in for debugging only.
                    MessageBox.Show(ex.ToString());
                }
                finally
                {
                    ServicePointManager.MaxServicePointIdleTime = temp;
                    //client.Dispose(); No dispose in .Net 2.0
                }
            }
        }
    }

SmtpClient の周りに Using を含める以外に機能上の違いはありません (コメントしたように、これは Framework 2.0 には適用されません)。

于 2010-11-09T19:55:54.397 に答える
2

これについてさらに考えてみると、Winsock 呼び出しを傍受し、送信後に送信メールをかじっている恐ろしいアンチウイルス システムの 1 つを持っているのではないかと思います。

どの A/V を実行していますか?

于 2010-11-09T20:21:17.020 に答える