C#如何阻止线程直到发送的电子邮件的所有响应到达

时间:2014-03-31 09:53:21

标签: c# multithreading

问题描述: 我想创建一个新线程来发送一些电子邮件。实现:

Thread _thread = new Thread(new ThreadStart(StartSendingEmails));

该函数名为:

public void StartSendingEmails()
        {
            var engine = new SendGridEmailEngine(From, FromName)
            {
                TemplateUrl = _templateUrl,
                QueryValues = _queryValues,
                MailHeaders = _mailHeaders
            };

            engine.SendEmail(EmailContent, Subject);
        }

发件人功能:

public void SendEmail(string emailContent, string subject)
        {
            int counter = 0;
            LastResponseReceived = DateTime.Now;

            foreach (var listItem in QueryValues)
            {
               //other operations....

                // 50 emails stack => wait...
                while (counter - ReceivedResponses > 50)
                    Thread.Sleep(100);

                //increase number of sent emails
                counter++;
                SendEmail(_from, _fromName);
            }

        //wait for all responses to be received
        while (ReceivedResponses < QueryValues.Count && (DateTime.Now - LastResponseReceived).TotalMinutes <= 2)
            Thread.Sleep(1000);

        //force exit if more than 2 min left and not all the responses received
        if (ReceivedResponses < QueryValues.Count && (DateTime.Now - LastResponseReceived).TotalMinutes >= 2)
            WriteLog(string.Format("Forced exit!);
}

致电:

public void SendEmail(string from, string fromName)
        {
            //other operations
            client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted);
        }
void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            ReceivedResponses++;
            LastResponseReceived = DateTime.Now;

            if (e.Error != null)
            {
            }
            else
            {
                SentEmailsSuccessfully++;
            }
        }

这就是问题所在。发送所有电子邮件但线程不等待所有响应。有没有办法比我用过的东西保持活力?

    //wait for all responses to be received
    while (ReceivedResponses < QueryValues.Count && (DateTime.Now - LastResponseReceived).TotalMinutes <= 2)
        Thread.Sleep(1000);

1 个答案:

答案 0 :(得分:2)

您应该将每个完整的发送操作封装到Task对象中。您可以await Task.WhenAll的结果等待所有任务完成。

List<Task> sendTasks = new List<Task>();

foreach (var listItem in QueryValues)
{
  sendTasks.Add(SendEmailAsync(_from, _fromName);
}

// wait for all responses to be received
await Task.WhenAll(sendTasks);

要提供一种取消操作的方法,如果花费的时间太长,只需使用超时的CancellationTokenSource

using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2)))
{
  List<Task> sendTasks = new List<Task>();

  foreach (var listItem in QueryValues)
  {
    sendTasks.Add(SendEmailAsync(_from, _fromName, cts.Token);
  }

  // wait for all responses to be received
  await Task.WhenAll(sendTasks.ToArray()).ConfigureAwait(false);
}