4

このリンクAsynchronous call をたどってみましたが、一部のクラスは廃止されています。
だから私は自分のプロジェクトに正確な答えが欲しい.

public class RegisterInfo
{
    public bool Register(UserInfo info)
    {
        try
        {
            using (mydatabase db = new mydatabase())
            {
                userinfotable uinfo = new userinfotable();
                uinfo.Name = info.Name;
                uinfo.Age = info.Age;
                uinfo.Address = info.Address;

                db.userinfotables.AddObject(uinfo);
                db.SaveChanges();

                // Should be called asynchronously
                Utility.SendEmail(info); // this tooks 5 to 10 seconds or more.

                return true;
            }
        }
        catch { return false; }
    }
} 

public class UserInfo
{
    public UserInfo() { }

    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}  

public class Utility
{
    public static bool SendEmail(UserInfo info)
    {
        MailMessage compose = SomeClassThatComposeMessage(info);
        return SendEmail(compose);
    }

    private static bool SendEmail(MailMessage mail)
    {
        try
        {
            SmtpClient client = new SmtpClient();
            client.Host = "smtp.something.com";
            client.Port = 123;
            client.Credentials = new System.Net.NetworkCredential("username@domainserver.com", "password");
            client.EnableSsl = true;

            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
            client.Send(mail);

            return true;
        }
        catch { return false; }
    }
}    

方法をご覧くださいRegister。データを保存した後、メールの送信を待ちたくありません。可能であれば、ユーザーが長時間待たないように、他のスレッドでメールの送信を処理したいと考えています。
メールが正常に送信されたかどうかを知る必要はありません。
私の言いたいことを理解していただければ幸いです。私の悪い英語でごめんなさい。

4

3 に答える 3

13

使用Thread:

new Thread(() => Utility.SendEmail(info)).Start();

使用ThreadPool:

ThreadPool.QueueUserWorkItem(s => Utility.SendEmail(info));

使用Task:

Task.Factory.StartNew(() => Utility.SendEmail(info));

もちろんThreadThreadPoolrequire using System.Threadingwhile Taskrequiresusing System.Threading.Tasks


David Andersonが述べたように、SmtpClient は既に非同期送信をサポートしています (おそらく、質問に答えるのではなく、関数の内容に注意を払うべきでした)。したがって、技術的には、それを使用して送信を処理することができますが、処理の負荷は軽減されません。メソッド全体の。

于 2012-04-12T03:43:47.480 に答える
3

SmtpClient には既にSendAsyncメソッドがあります。これを行うために独自の非同期コードを記述する必要はありません。

SmtpClient が ASP.NET でそのままでは機能しないことに関する @Comment:
これはまったく正しくありません。うまく機能し、推奨される API です。ただし、ASP.NET ページのライフサイクルと、サーバー上でのスレッドの動作を理解する必要があります。そうでなければ、それを使用しない理由はありません。

于 2012-04-12T03:49:36.160 に答える
2

またはAsync CTPを使用します。

public async Task<bool> Register(UserInfo info)
{
    try
    {
        using (mydatabase db = new mydatabase())
        {
            userinfotable uinfo = new userinfotable();
            uinfo.Name = info.Name;
            uinfo.Age = info.Age;
            uinfo.Address = info.Address;

            db.userinfotables.AddObject(uinfo);
            db.SaveChanges();

            //Wait for task to finish asynchronously
            await Utility.SendEmail(info);

            return true;
        }
    }
    catch { return false; }
}

private Task SendEmail(MailMessage mail)
{
    SmtpClient client = new SmtpClient();
    client.Host = "smtp.something.com";
    client.Port = 123;
    client.Credentials = new System.Net.NetworkCredential("username@domainserver.com", "password");
    client.EnableSsl = true;

    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

    //The smtp SendTaskAsync is an extension method when using Async CTP
    return client.SendTaskAsync("from", "recipients", "subject", "body");
}

元のコードにもバグがあります。SendEmail 関数内で例外がスローされると false が返されますが、register 関数内では true が返されます。bool が成功または失敗を意味すると仮定します。

于 2012-04-12T04:24:48.390 に答える