重定向到另一个aspx页面并在后台运行下一个代码(.NET 4.5.2)

时间:2017-06-26 18:50:01

标签: c# asp.net multithreading async-await

我正在开发一个ASP.NET Webform项目(遗留代码)。在我的button_click事件中,我将sms消息发送到此处填充的所有数据。

 var customerSMS = BusinessLayer.SMS.SmsSetup.GetAllCustomerSMS(OfficeId);

这需要大约15seconds进行所有计算并获取数据(1000rows)

来自Db的

。对于每个数据,它运行循环并进行验证和

发送短信,确实需要时间。我想在后台执行此任务,

将用户重定向到索引页面,后台进程一直持续到

离开了循环。我是新手,仍在学习这个美丽的

语言C#。我确实经历了这个惊人的异步编程async / await

和多线程方法只在简单的WindowsForm中得到它

applications.Any参考/代码片段/最佳方法以及对我的案例的简单解释会有所帮助。

我的按钮点击事件代码

    protected void ReturntoDashboard_Click(object sender, EventArgs e)
    { 

         sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
         if (sms.EnableSmsData && sms.SmsCount > 0)
         {
         #region Loan Section
           var smsLoan = Everest.Net.BusinessLayer.SMS.SmsSetup.GetLoanId(s.Sms_AccountNumber);
          var loanId =
             BusinessLayer.SMS.SmsSetup.GetLoanIdValue(s.Sms_AccountNumber);
             var dateexceeded =
             BusinessLayer.SMS.SmsSetup.IsDateExceeded(loanId);
             if (smsLoan != null && dateexceeded == true)
                 {
                  foreach (Common.SMS.SMSSetup sm in smsLoan)
                    {           

                        var smsClosingBalanceLoan = BusinessLayer.SMS.SmsSetup.GetAmountForLoanAlert(  sm.LoanId,
                                                                BusinessLayer.Core.DateConversion
                                                                    .GetCurrentServerDate()
                                                                    .AddDays(sms.DaysbeforeLoanalerts).ToString());

                   if (smsClosingBalanceLoan != null)
                       {
                         if (smsClosingBalanceLoan.LoanAmountToPay > 0)
                           {
                             int smsSentAlertCount = sms.LoanAlertCount;
                                var logCount = BusinessLayer.SMS.SmsSetup.GetLoanSmsAlertSentCount(DateTime.Now.AddDays(-smsSentAlertCount).ToString("yyyy-MM-dd"), DateTime.Now.ToString("yyyy-MM-dd"), sm.LoanAccountNumber);
                                  if (logCount < smsSentAlertCount)
                                     {
                                      smsLog = new Everest.Net.Common.SMS.SMSSetup();
                                          finalMessage = "Dear Member, Your Loan accnt " + sm.LoanAccountNumber + " with Principal"+ "+" + "Int Amnt: Rs." + smsClosingBalanceLoan.LoanAmountToPay + " need to be payed.Thank You," + officeName.OfficeName;

                                             smsLog.LogServiceType = "Loan";
                                             smsLog.LogSmsType = s.Sms_SmsType;
                                             smsLog.LogSmsMessage = finalMessage;
                                             smsLog.LogCustomerId = s.CustomerId.ToString();
                                             smsLog.LogAccountNumber = s.Sms_AccountNumber;
                                             smsLog.LogAccountType = s.Sms_AccountType;
                                             smsLog.LogSmsSentDate = BusinessLayer.Core.DateConversion.GetCurrentServerDate();
                                             smsLog.LogSmsFailedDate = "";
                                             smsLog.LogSentStatus = true;
                                             smsLog.LogUserId = UserId;
                                             smsLog.LogSmsFailedMessage = "";
                                             try
                                              {
                                                 var result = Everest.Net.BusinessLayer.SMS.smsParameters.SendSMS(sms.FromNum, sms.Token, sms.Url, cellNum, finalMessage);
                                              }
                                             catch (Exception ex)
                                              {
                                                  smsLog.LogSmsFailedDate = System.DateTime.Now.ToString("MM/dd/yyyy HHmmss");
                                                  smsLog.LogSentStatus = false;
                                                  smsLog.LogSmsFailedMessage = ex.Message;
                                                  Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
                                              }
                                              sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
                                              sms.SmsCount = sms.SmsCount - 1;
                                              Everest.Net.BusinessLayer.SMS.SmsSetup.UpdateSmsSetup(sms);
                                              Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
                                        }
                                    }
                               }
                          }
                   }


             }

     }
 }
  catch (Exception ex)

1 个答案:

答案 0 :(得分:2)

理想的解决方案将消除从Web应用程序本身发送SMS的责任。相反,Web应用程序应创建包含消息和收件人地址的数据库记录,并且单独的后台作业(例如Windows服务)应轮询数据库并在需要时发送SMS消息。这是容错和可审计性方面的最佳解决方案,因为有一个消息传递作业的永久记录,如果系统出现故障,可以恢复该记录。

话虽这么说,也许你不想去那么麻烦。如果您强烈希望直接从ASP.NET应用程序发送SMS,则需要创建Task并将其排队以使用QueueBackgroundWorkitem运行。您需要稍微重构一下代码。

  1. 将发送SMS的所有逻辑移动到一个单独的函数中,该函数接受作为参数所需的所有信息。例如,

    static void SendSMS(string[] addresses, string messagetext)
    {
        //Put your SMS code here
    }
    
  2. 当您需要调用该函数时,将其排队为背景项

    HostingEnvironment.QueueBackgroundWorkItem(a => SendSMS(addresses, messageText)); 
    
  3. 如果您的工作人员任务需要访问自己的取消令牌(例如,如果它应该循环直到取消),它将作为参数传递给lambda表达式。所以你可以修改原型

     static void SendSMS(string[] addresses, string messagetext, CancellationToken token)
     {
          while (!token.IsCancellationRequested) 
          {
              //Put your code here
          }
     }
    

    并通过它:

    HostingEnvironment.QueueBackgroundWorkItem(token => SendSMS(addresses, messageText, token));
    
  4. 将任务放在后台队列中可确保ASP.NET跟踪线程,不会尝试对其进行垃圾回收,并在应用程序池需要关闭时正确关闭它。

    排队后台操作后,您的页面可以按常规呈现内容,并在任务继续执行时结束HTTP响应。