4

我试过关注这个链接异步调用,但有些类已经过时了。
所以我想为我的项目提供一个准确的答案。

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

当然ThreadThreadPool需要using System.Threading同时Task需要using System.Threading.Tasks


正如David Anderson所说,SmtpClient 已经支持异步发送 (我可能应该注意函数的内容而不是回答问题),所以从技术上讲,您可以使用它来处理发送,尽管它不会卸载处理你的整个方法。

于 2012-04-12T03:43:47.480 回答
3

SmtpClient 已经有一个SendAsync方法。您不需要编写自己的异步代码来执行此操作。

@Comment 关于 SmtpClient 在 ASP.NET 中不能开箱即用:
这绝对不是真的,它工作得很好并且是推荐的 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 回答