2011-07-31 91 views
1

我有一个网站我管理一个客户端,他们希望能够发送电子邮件到他们的所有成员。我联系了主机,他们建议每隔一分钟发送一次,以便邮件服务器不会超载。在asp.net中的线程

听起来很不错,但我能想到的唯一办法做到这一点,而不会导致管理员必须坐在一个页面上同时发送电子邮件和各批次之间的重载是有一个页面调用,它发射了一个ASHX处理程序一个线程完成工作,并且线程在每个批次后设置为睡眠60秒。

当我从我的机器运行代码时,它工作正常,并完成整个电子邮件列表。当我从web主机运行它时,我无法访问ftp,它几乎完成但没有。然后,如果我再次尝试点击ashx页面以完成未发送的内容,则不会执行任何操作。这就像线程可能会导致某些东西锁定,并阻止其他线程运行。

下面是我使用的代码,我从来没有使用过线程之前...有没有人知道为什么它可能会这样做,以及如何使它正常工作?我完成后是否需要专门杀死线程?如果是这样,怎么样?谢谢。

public void ProcessRequest(HttpContext context) 
    { 

     if (context.Request.QueryString["id"].IsValid<int>()) 
     { 
      campaignId = context.Request.QueryString["id"].To<int>(); 
      var t = new Thread(new ThreadStart(SendEmails)) 
         { 
          Priority = ThreadPriority.Lowest 
         }; 
      t.Start(); 
     } 
    } 

    private void SendEmails() 
    { 
     int currentCount = 0; 
     BroadcastEmailCampaign campaign = EmailController.GetCampaign(campaignId, false); 
     List<Member> memberlist = EmailController.GetEmailList(campaign.CampaignId); 

     var message = new MailMessage 
          { 
           Body = campaign.Body, 
           From = new MailAddress(campaign.SentBy), 
           IsBodyHtml = true, 
           Subject = campaign.Subject, 
           BodyEncoding = Encoding.UTF8 
          }; 

     //add attachment 
     if (!string.IsNullOrEmpty(campaign.Attachment) && File.Exists(campaign.Attachment)) 
     { 
      var attachment = new Attachment(campaign.Attachment); 
      EmailAttachmentType.SetContentProperites(campaign.Attachment, ref attachment); 
      message.Attachments.Add(attachment); 
     } 

     if (memberlist.Count <= 0) 
     { 
      return; 
     } 

     bool sendingComplete = false; 
     EmailController.SetCampaignSendingStatus(true, campaign.CampaignId); 

     while (sendingComplete == false) 
     { 
      message.Bcc.Clear(); 
      message.To.Clear(); 

      message.To.Add(new MailAddress(dummyEmailAddress)); 

      List<Member> emailsToSend = memberlist.Skip(currentCount).Take(takeCount).ToList(); 

      if (emailsToSend.Count <= 0) 
      { 
       sendingComplete = true; 
       EmailController.LogEmailCampaignResult(campaign); 
       EmailController.SetCampaignSendingStatus(false, campaign.CampaignId); 

      } 

      if (!sendingComplete) 
      { 
       foreach (Member email in emailsToSend) 
       { 
        message.Bcc.Add(new MailAddress(email.Email)); 
        campaign.SentTo.Add(new BroadcastEmailCampaignSentTo 
              { 
               MemberId = email.MemberId, 
               Email = email.Email, 
               DateSent = DateTime.Now 
              }); 
       } 

       EmailController.SendEmail(message); 
       EmailController.LogEmailsSent(emailsToSend, campaignId); 

       currentCount += takeCount; 

       Thread.Sleep(pauseTime); 
      } 
     } 

    } 

回答

0

t.IsBackground = true;

如果不这样做,我建议使用带有QueueUserWorkItem的ThreadPool。

+0

我会试试看。谢谢! –

1

由于我在ASP.NET中阅读了很多线程,并且仍然没有真正的dos和donts的线索,所以我通常解决的任务就像由Windows任务计划程序中的计划任务运行的控制台应用程序描述的那样。 5分钟:

  1. 在ASP.NET页面中,我写的所有必需的信息到数据库表。
  2. 调度程序定期轮询数据库表以查找新作业(例如发送电子邮件)和进程,然后清空充当队列的数据库表。

这使我的应用程序保持响应,另外我不担心,一个IISRESET或类似这样的东西会杀了我的后台线程。