简体   繁体   English

如何异步调用方法

[英]How to call a method asynchronously

I've tried following this link Asynchronous call but some classes are obsolete. 我试过跟这个链接异步调用,但有些类已经过时了。
So I want an exact answer for my project. 所以我想为我的项目准确回答。

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

Please look at the Register method. 请查看Register方法。 After saving the data, I don't want to wait for the sending of mail. 保存数据后,我不想等待发送邮件。 If possible I want to process the sending of mail on other thread so the user will not wait for a longer time. 如果可能的话,我想处理在其他线程上发送邮件,这样用户就不会等待更长的时间。
I don't need to know if mail has sent successfully. 我不需要知道邮件是否已成功发送。
Hope you could understand what I mean. 希望你能明白我的意思。 Sorry for my bad English. 对不起,我的英语不好。

Using Thread : 使用Thread

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

Using ThreadPool : 使用ThreadPool

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

Using Task : 使用Task

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

Of course Thread and ThreadPool require using System.Threading while Task requires using System.Threading.Tasks 当然, ThreadThreadPool需要using System.ThreadingTask需要using System.Threading.Tasks


As stated by David Anderson , SmtpClient already supports asynchronous send (I probably should have paid attention to the content of the function rather than answering the question) , so technically you could just use that to handle the send though it won't offload the processing of your entire method. 正如David Anderson所说,SmtpClient已经支持异步发送 (我可能应该注意函数的内容而不是回答问题) ,所以从技术上讲,你可以使用它来处理发送,尽管它不会卸载处理你的整个方法。

请尝试以下链接: ThreadPool.QueueUserWorkitem

SmtpClient has already has a SendAsync method. SmtpClient已经有了SendAsync方法。 You don't need to write your own asynchronous code to do this. 您不需要编写自己的异步代码来执行此操作。

@Comment regarding that SmtpClient does not work out of the box with ASP.NET: 关于SmtpClient的@Comment不能与ASP.NET一起开箱即用:
This is absolutely just not true, it works great and is the recommended API. 这绝对不是真的,它运行良好,是推荐的API。 You however must understand the ASP.NET Page Life-Cycl e and how threading behaves on the server. 但是,您必须了解ASP.NET Page Life-Cycl e以及线程在服务器上的行为方式。 Otherwise there is no reason not to use it. 否则没有理由不使用它。

Or using Async CTP . 或者使用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");
}

There is also a bug in your original code. 您的原始代码中也存在错误。 When an exception is thrown inside SendEmail function, it returns false but inside the register function it will still return true. 当SendEmail函数内部抛出异常时,它返回false,但在寄存器函数内它仍将返回true。 Assuming that the bool signifies success or failure. 假设bool表示成功或失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM