SmtpClient.SendAsync - 如何在触发回调之前停止应用程序退出?

发布于 2024-08-12 01:27:43 字数 1732 浏览 6 评论 0原文

我需要通过控制台应用程序异步发送电子邮件。我需要对回调进行一些数据库更新,但我的应用程序在回调代码运行之前就退出了!

我怎样才能以一种好的方式阻止这种情况发生,而不是简单地猜测退出之前需要等待多长时间。我想异步调用会被放置在某种形式的线程中?是否可以检查是否有人正在等待呼叫?

示例代码

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
   // Get the unique identifier for this asynchronous operation.
   String token = (string) e.UserState;
   if (e.Cancelled)
   {
      Console.WriteLine("[{0}] Send canceled.", token);
   }
   if (e.Error != null)
   {
      Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
   } 
   else
   {
       // update DB
       Console.WriteLine("Message sent.");
   }
}

public static void Main(string[] args)
{
    var users = Repository.GetUsers();
    SmtpClient client = new SmtpClient("Host");
    client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8);
    foreach (var user in users)
    {
        MailAddress to = new MailAddress(user.Email);
        MailMessage message = new MailMessage(from, to);
        message.Body = "This is a test";
        message.BodyEncoding =  System.Text.Encoding.UTF8;
        message.Subject = "test message 1" + someArrows;
        message.SubjectEncoding = System.Text.Encoding.UTF8;
        string userState = String.Format("Message for user id {0}", user.ID);
        client.SendAsync(message, userState);
        message.Dispose();   
    }

    // need to wait here until I have received a callback for each message
    // otherwise the application will exit
}

I need to send emails asychronously through a console application. I need to do some DB updates on the callback but my application is exiting before the callback code gets run!

How can I stop this from happening in a nice manner rather than simply guessing how long to wait before exiting. I would imagine the Async calls get placed in some form of thread? Is it possible to check if any are waiting to be called?

Sample Code

private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
   // Get the unique identifier for this asynchronous operation.
   String token = (string) e.UserState;
   if (e.Cancelled)
   {
      Console.WriteLine("[{0}] Send canceled.", token);
   }
   if (e.Error != null)
   {
      Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
   } 
   else
   {
       // update DB
       Console.WriteLine("Message sent.");
   }
}

public static void Main(string[] args)
{
    var users = Repository.GetUsers();
    SmtpClient client = new SmtpClient("Host");
    client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8);
    foreach (var user in users)
    {
        MailAddress to = new MailAddress(user.Email);
        MailMessage message = new MailMessage(from, to);
        message.Body = "This is a test";
        message.BodyEncoding =  System.Text.Encoding.UTF8;
        message.Subject = "test message 1" + someArrows;
        message.SubjectEncoding = System.Text.Encoding.UTF8;
        string userState = String.Format("Message for user id {0}", user.ID);
        client.SendAsync(message, userState);
        message.Dispose();   
    }

    // need to wait here until I have received a callback for each message
    // otherwise the application will exit
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盗心人 2024-08-19 01:27:43

创建一个ManualResetEvent,在退出之前调用WaitOne 就可以了。当执行最后一次电子邮件/数据库更新时,调用 ManualResetEvent 上的 Set。


public static void Main(string[] args)
{
    object someArrows = ">>>";
    var users = Repository.GetUsers();
    SmtpClient client = new SmtpClient("Host");
    client.SendCompleted += SendCompletedCallback;
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8);
    int numRemaining = users.Length;
    using(ManualResetEvent waitHandle = new ManualResetEvent(numRemaining == 0))
    {
        object numRemainingLock = new object();
        foreach(var user in users)
        {
            MailAddress to = new MailAddress(user.Email);
            MailMessage message = new MailMessage(from, to);
            try
            {
                message.Body = "This is a test";
                message.BodyEncoding = System.Text.Encoding.UTF8;
                message.Subject = "test message 1" + someArrows;
                message.SubjectEncoding = System.Text.Encoding.UTF8;
                string userState = String.Format("Message for user id {0}", user.ID);
                client.SendCompleted += delegate
                {
                    lock(numRemainingLock)
                    {
                        if(--numRemaining == 0)
                        {
                            waitHandle.Set();
                        }
                    }
                };
                client.SendAsync(message, userState);
            }
            catch
            {
                message.Dispose();
                throw;
            }
        }
        waitHandle.WaitOne();
    }
}

Create a ManualResetEvent call WaitOne one it on it before exiting. When the last email/dbupdate is performed, call Set on the ManualResetEvent.


public static void Main(string[] args)
{
    object someArrows = ">>>";
    var users = Repository.GetUsers();
    SmtpClient client = new SmtpClient("Host");
    client.SendCompleted += SendCompletedCallback;
    MailAddress from = new MailAddress("[email protected]", "System", Encoding.UTF8);
    int numRemaining = users.Length;
    using(ManualResetEvent waitHandle = new ManualResetEvent(numRemaining == 0))
    {
        object numRemainingLock = new object();
        foreach(var user in users)
        {
            MailAddress to = new MailAddress(user.Email);
            MailMessage message = new MailMessage(from, to);
            try
            {
                message.Body = "This is a test";
                message.BodyEncoding = System.Text.Encoding.UTF8;
                message.Subject = "test message 1" + someArrows;
                message.SubjectEncoding = System.Text.Encoding.UTF8;
                string userState = String.Format("Message for user id {0}", user.ID);
                client.SendCompleted += delegate
                {
                    lock(numRemainingLock)
                    {
                        if(--numRemaining == 0)
                        {
                            waitHandle.Set();
                        }
                    }
                };
                client.SendAsync(message, userState);
            }
            catch
            {
                message.Dispose();
                throw;
            }
        }
        waitHandle.WaitOne();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文