我正在开发一个ASP.NET Webform项目(遗留代码)。在我的button_click事件中,我将sms消息发送到此处填充的所有数据。
var customerSMS = BusinessLayer.SMS.SmsSetup.GetAllCustomerSMS(OfficeId);
这需要大约15seconds
进行所有计算并获取数据(1000rows)
。对于每个数据,它运行循环并进行验证和
发送短信,确实需要时间。我想在后台执行此任务,
将用户重定向到索引页面,后台进程一直持续到
离开了循环。我是新手,仍在学习这个美丽的
语言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)
答案 0 :(得分:2)
理想的解决方案将消除从Web应用程序本身发送SMS的责任。相反,Web应用程序应创建包含消息和收件人地址的数据库记录,并且单独的后台作业(例如Windows服务)应轮询数据库并在需要时发送SMS消息。这是容错和可审计性方面的最佳解决方案,因为有一个消息传递作业的永久记录,如果系统出现故障,可以恢复该记录。
话虽这么说,也许你不想去那么麻烦。如果您强烈希望直接从ASP.NET应用程序发送SMS,则需要创建Task
并将其排队以使用QueueBackgroundWorkitem运行。您需要稍微重构一下代码。
将发送SMS的所有逻辑移动到一个单独的函数中,该函数接受作为参数所需的所有信息。例如,
static void SendSMS(string[] addresses, string messagetext)
{
//Put your SMS code here
}
当您需要调用该函数时,将其排队为背景项
HostingEnvironment.QueueBackgroundWorkItem(a => SendSMS(addresses, messageText));
如果您的工作人员任务需要访问自己的取消令牌(例如,如果它应该循环直到取消),它将作为参数传递给lambda表达式。所以你可以修改原型
static void SendSMS(string[] addresses, string messagetext, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Put your code here
}
}
并通过它:
HostingEnvironment.QueueBackgroundWorkItem(token => SendSMS(addresses, messageText, token));
将任务放在后台队列中可确保ASP.NET跟踪线程,不会尝试对其进行垃圾回收,并在应用程序池需要关闭时正确关闭它。
排队后台操作后,您的页面可以按常规呈现内容,并在任务继续执行时结束HTTP响应。