我有一个从Global.asax文件开始的WCF应用程序,有一个应用程序启动事件,代码如下:
public class Global : HttpApplication
{
private bool isInitialized = false;
private static readonly ILog log = LogManager.GetLogger(typeof(Global));
private PushController pushController;
private Task pushMonitoringTask;
protected void Application_Start(object sender, EventArgs e)
{
Initialize();
pushMonitoringTask = Task.Run(() => pushController.StartMonitoring());
}
...}
推送控制器:
public class PushController
{
private IRepository<Question> QuestionRepository { get; set; }
private IRepository<Mobile_Report> ReportRepository { get; set; }
private readonly string _syncFilePath;
private readonly string certificatePath;
private readonly PushBroker _broker;
private bool _isStopRequired;
public PushController(IRepository<Question> questionRepository, IRepository<Mobile_Report> reportsRepository, HttpServerUtility server)
{
QuestionRepository = questionRepository;
ReportRepository = reportsRepository;
_broker = new PushBroker();
_syncFilePath = server.MapPath("~/SyncFile.txt");
certificatePath = "My cert path";
if (!File.Exists(_syncFilePath))
{
using (StreamWriter sw = File.AppendText(_syncFilePath))
{
sw.WriteLine(DateTime.Now);
sw.Flush();
}
}
_isStopRequired = false;
}
public void StartMonitoring()
{
var delay = Convert.ToInt32(ConfigurationManager.AppSettings["NewQuestionsMonitoringDelay"]);
RunPushServices();
while (!_isStopRequired)
{
using (var fileStream = new FileStream(_syncFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
DateTime lastSyncDate;
using (var sw = new StreamReader(fileStream))
{
lastSyncDate = Convert.ToDateTime(sw.ReadLine());
}
if (lastSyncDate == default(DateTime))
{
throw new Exception("Corrupted or missing sync date");
}
EnqueueNotificationsList(lastSyncDate);
using (var sw = new StreamWriter(_syncFilePath, false))
{
sw.WriteLine(DateTime.Now);
sw.Flush();
}
}
Thread.Sleep(delay * 1000);
}
//_broker.StopAllServices();//waits for the queue to drain
}
private void RunPushServices()
{
_broker.RegisterAppleService(new ApplePushChannelSettings(false, certificatePath, "My cert password"));
//_broker.RegisterGcmService(new GcmPushChannelSettings("senderId", "sender auth token", "android app package name"));
}
private void EnqueueNotificationsList(DateTime lastSyncDate)
{
var newQuestions = QuestionRepository.GetAll().Where(q => q.UtcDateCreated >= lastSyncDate);
var newReports = ReportRepository.GetAll().Where(r => r.CreatedDate >= lastSyncDate);
EnqueueQuestionsNotifications(newQuestions);
EnqueueReportsNorifications(newReports);
}
private void EnqueueQuestionsNotifications(IEnumerable<Question> newQuestions)
{
foreach (var questionGroup in newQuestions.GroupBy(q => q.Mobile_Sample))
{
var firstQuestion = questionGroup.First();
var targetSample = firstQuestion.Mobile_Sample;
var allSessions = firstQuestion.Mobile_Sample.Mobile_Claim.Mobile_Contact.UserSession;
var questionsNotificationString = BuildQuestionsNotificationString(targetSample, questionGroup.Count());
foreach (var userSession in allSessions)
{
switch (userSession.DeviceType)
{
case (int)DeviceType.IOSDeivce:
_broker.QueueNotification(new AppleNotification()
.ForDeviceToken(userSession.DeviceToken)
.WithAlert(questionsNotificationString)
.WithBadge(1)
.WithSound("default")
.WithCustomItem("PushInfo", "Questions", targetSample.ID));
break;
//case (int)DeviceType.AndroidDevice:
// _broker.QueueNotification(
// new GcmNotification().ForDeviceRegistrationId(userSession.DeviceToken)
// .WithJson(@"{""alert"":""ITEL Questions"",""badge"":7,""sound"":""sound.caf""}");
// break;
}
}
}
}
private void EnqueueReportsNorifications(IEnumerable<Mobile_Report> newReports)
{
foreach (var reportsGroup in newReports.GroupBy(q => q.Mobile_Sample))
{
var firstReport = reportsGroup.First();
var targetSample = firstReport.Mobile_Sample;
var allSessions = firstReport.Mobile_Sample.Mobile_Claim.Mobile_Contact.UserSession;
var reportNotificationString = BuildReportNotificationString(targetSample);
foreach (var userSession in allSessions)
{
switch (userSession.DeviceType)
{
case (int)DeviceType.IOSDeivce:
_broker.QueueNotification(new AppleNotification()
.ForDeviceToken(userSession.DeviceToken)
.WithAlert(reportNotificationString)
.WithBadge(1)
.WithSound("default")
.WithCustomItem("Target", "Reports", targetSample.ID));
break;
//case (int)DeviceType.AndroidDevice:
// _broker.QueueNotification(
// new GcmNotification().ForDeviceRegistrationId(userSession.DeviceToken)
// .WithJson(@"{""alert"":""ITEL Questions"",""badge"":7,""sound"":""sound.caf""}");
// break;
}
}
}
}
private string BuildQuestionsNotificationString(Mobile_Sample targetSample, int count)
{
var claimLastNameString = !string.IsNullOrEmpty(targetSample.Mobile_Claim.IILastName)
? " " + targetSample.Mobile_Claim.IILastName
: string.Empty;
var claimNumberString = !string.IsNullOrEmpty(targetSample.Mobile_Claim.ClaimNumber)
? " Claim #" + targetSample.Mobile_Claim.ClaimNumber + ", "
: " Claim # -";
var areaDamagedString = !string.IsNullOrEmpty(targetSample.AreaDamaged)
? " (" + targetSample.AreaDamaged + ")"
: string.Empty;
return "You have " + count + " new questions for" + claimLastNameString + claimNumberString + targetSample.Mobile_SampleType.Name + areaDamagedString;
}
private string BuildReportNotificationString(Mobile_Sample targetSample)
{
var claimLastNameString = !string.IsNullOrEmpty(targetSample.Mobile_Claim.IILastName)
? " " + targetSample.Mobile_Claim.IILastName
: string.Empty;
var claimNumberString = !string.IsNullOrEmpty(targetSample.Mobile_Claim.ClaimNumber)
? " Claim #" + targetSample.Mobile_Claim.ClaimNumber + ", "
: " Claim # -";
var areaDamagedString = !string.IsNullOrEmpty(targetSample.AreaDamaged)
? " (" + targetSample.AreaDamaged + ")"
: string.Empty;
return "You have a new report for" + claimLastNameString + claimNumberString + targetSample.Mobile_SampleType.Name + areaDamagedString;
}
public void RequestMonitoringStop()
{
_isStopRequired = true;
}
}
因此您可以看到我实际上是在Global.asax中启动了一个终止于Application_End的后台任务。问题是线程周期性卡住并且不再继续(可能是静默崩溃或其他任何事情),因此SyncFile不会更新,也没有新的通知被推送到客户端,服务器的主要功能仍在运行虽然,这也是一个棘手的事情 - 我不能在本地重现问题,只有当服务器部署到生产服务器时才会出现,也许在HttpApplication中有一些关于任务的问题,或者我错过了什么?提前谢谢。
答案 0 :(得分:0)
找到解决方案 - 如果没有20(默认)分钟的请求,网站将进入“空闲”状态,必须编辑IIS设置。