에 갇히지, 코드는 다음과 같다 :스레드 응용 프로그램의 시작 이벤트가, 내가 Global.asax 파일에서 시작하는 WCF 응용 프로그램이 같이 HttpApplication
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의 작업에 대한 문제가 있거나 누락 된 부분이 있습니까? 미리 감사드립니다.