2013-12-12 6 views
0

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

답변

0

해결책을 찾았습니다 - 20 (기본값) 분 동안 요청이 없으면 사이트가 "유휴 상태"가되어 IIS 설정을 편집해야합니다.