2010-10-20 26 views
3

Je reçois cette erreur dans mes journaux d'événements pour un service que je mis en production:C# basé sur Windows service - essaie de faire Débogage JIT dans la production

An unhandled win32 exception occurred in RivWorks.FeedHandler.exe [5496]. Just-In-Time debugging this exception failed with the following error: Debugger could not be started because no user is logged on.

Je l'ai installé et fonctionne sous Windows NT global Compte. Je ne sais pas pourquoi il essaie de passer en mode de débogage. Il a été construit sous le modèle Release. En cours d'exécution sur le Framework 4.0. Lorsque je cours sur ma machine de développement, via un point d'entrée EXE au lieu du point d'entrée WinSvc, tout fonctionne très bien - MAIS - Je suis déjà en mode "debug".

Des idées de quoi chercher?


2010-10-21 - NOTE - Modification de la base de code.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Linq; 
using System.ServiceProcess; 
using System.Text; 
using System.IO; 
using sysIO = System.IO; 
using RivWorks.FeedHandler; 
using System.Collections; 

namespace RivWorks.FeedHandler.Service 
{ 
    public partial class FeedListener : ServiceBase 
    { 
     #region Declarations 
     private List<string> _keys = new List<string>(); 
     private System.Threading.Timer _clock = null; 
     private FileSystemWatcher _watcher; 
     private BackgroundWorker _worker; 
     private Queue<string> _queue = new Queue<string>(); 
     private bool _isDequeueing = false; 
     #endregion 

     #region Constructor 
     public FeedListener() 
     { 
      InitializeComponent(); 
     } 
     #endregion 

     #region Start/Stop 
     protected override void OnStart(string[] args) 
     { 
      try 
      { 
       WriteToEventLog("Enter Start", EventLogEntryType.Information); 
       _keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" }); 

       _worker = new BackgroundWorker(); 
       _worker.WorkerReportsProgress = true; 
       _worker.WorkerSupportsCancellation = true; 
       _worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork); 
       _worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorkerProgressChanged); 
       _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerRunWorkerCompleted); 

       _watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*"); 
       _watcher.IncludeSubdirectories = true; 
       _watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite; 
       _watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
       _watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
       _watcher.EnableRaisingEvents = true; 

       // check every 15 minutes... 
       _clock = new System.Threading.Timer(Tick, null, 0, 900000); 
       WriteToEventLog("Exit Start", EventLogEntryType.Information); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
       this.Stop(); 
      } 
     } 
     protected override void OnStop() 
     { 
      try 
      { 
       _watcher.Dispose(); 
       _watcher = null; 
       _clock.Dispose(); 
       _clock = null; 
       _worker.Dispose(); 
       _worker = null; 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Event Handlers 
     void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e) 
     { 
      try 
      { 
       WriteToEventLog("Enter fileCreatedOrChanged", EventLogEntryType.Information); 

       if (!_queue.Contains(e.FullPath)) 
        _queue.Enqueue(e.FullPath); 
       if (!_isDequeueing) 
        DeQueue(); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Do work on another Thread 
     void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       WriteToEventLog("Enter BackgroundWorkerDoWork", EventLogEntryType.Information); 
       BackgroundWorker bw = sender as BackgroundWorker; 

       WriteToEventLog("Create Handler", EventLogEntryType.Information); 
       RivWorks.FeedHandler.Library.Handler handler = new RivWorks.FeedHandler.Library.Handler(Convert.ToBoolean(AppSettings.Default.InProduction), AppSettings.Default.ArchivePath); 

       WriteToEventLog("Setup Handler", EventLogEntryType.Information); 
       handler.Keys = _keys; 
       handler.RootDirectory = AppSettings.Default.RootDirectory; 
       handler.FtpPath = AppSettings.Default.FTPRootPath; 
       handler.WorkPath = AppSettings.Default.WorkPath; 
       handler.ArchivePath = AppSettings.Default.ArchivePath; 
       handler.EmailHost = AppSettings.Default.EmailHost; 
       handler.EmailPassword = AppSettings.Default.EmailPassword; 
       handler.EmailUser = AppSettings.Default.EmailUser; 
       handler.ErrorNotificationRecipients = AppSettings.Default.ErrorNotificationRecipients; 
       handler.InProduction = Convert.ToBoolean(AppSettings.Default.InProduction); 

       Library.DTO.FileHandler fileHandler = new Library.DTO.FileHandler(handler.FtpPath, handler.WorkPath, handler.ArchivePath, (string)e.Argument); 

       WriteToEventLog("Call Handler.Execute", EventLogEntryType.Information); 
       handler.Execute(bw, e, fileHandler); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
      finally 
      { 
       WriteToEventLog("Exit BackgroundWorkerDoWork", EventLogEntryType.Information); 
      } 
     } 
     void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      try 
      { 
       if (e.ProgressPercentage >= 100) 
       { 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      try 
      { 
       if (e.Cancelled) 
       { 
        WriteToEventLog("Cancelled.", EventLogEntryType.Warning); 
        if (e.Error != null) 
        { 
         WriteToEventLog(e.Error, EventLogEntryType.Error); 
        } 
       } 
       else if (e.Error != null) 
       { 
        WriteToEventLog(e.Error, EventLogEntryType.Error); 
       } 
       else 
       { 
        WriteToEventLog("Successfully completed.", EventLogEntryType.Information); 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Private Methods 
     private void Tick(object data) 
     { 
      try 
      { 
       if (!_isDequeueing) 
       { 
        WriteToEventLog("Enter Tick. FTP Root = " + AppSettings.Default.FTPRootPath, EventLogEntryType.Information); 

        foreach (string key in _keys) 
        { 
         List<string> files = Directory.GetFiles(Path.Combine(AppSettings.Default.FTPRootPath), "*." + key, SearchOption.AllDirectories).ToList(); 
         foreach (string fileName in files) 
         { 
          if (File.Exists(fileName)) 
          { 
           // Toss this file name into the Queue... 
           WriteToEventLog("Call _queue.Enqueue(" + fileName + ")", EventLogEntryType.Information); 
           if (!_queue.Contains(fileName)) 
            _queue.Enqueue(fileName); 
          } 
         } 
        } 
        // Now, start handling the list of files... 
        DeQueue(); 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
      finally 
      { 
       WriteToEventLog("Exit Tick", EventLogEntryType.Information); 
      } 
     } 
     private void DeQueue() 
     { 
      try 
      { 
       _isDequeueing = true; 

       WriteToEventLog("Enter DeQueue", EventLogEntryType.Information); 

       while (_queue.Count > 0) 
       { 
        string queuedFile = _queue.Dequeue(); 
        WriteToEventLog("DeQueued " + queuedFile, EventLogEntryType.Information); 

        bool isValid = false; 
        foreach (string key in _keys) 
        { 
         if (Path.GetExtension(queuedFile).Replace(".", "").Equals(key, StringComparison.CurrentCultureIgnoreCase)) 
          isValid = true; 
        } 

        if (isValid) 
        { 
         // Now, spin up a new thread and do the work on the file, based on file type... 
         WriteToEventLog("Call RunWorkerAsync", EventLogEntryType.Information); 
         string UserName = Path.GetDirectoryName(queuedFile).Replace(AppSettings.Default.FTPRootPath, "").Replace("\\", ""); 
         int i = 0; 
         DateTime sTime = DateTime.Now; 
         DateTime eTime = DateTime.Now; 
         _worker.RunWorkerAsync(queuedFile); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) // 

         while(_worker.IsBusy) 
         { 
          System.Threading.Thread.Sleep(5000); 
          i++; 
         } 
         eTime = DateTime.Now; 
         TimeSpan ts = new TimeSpan(eTime.Ticks - sTime.Ticks); 
         string msg = String.Format("Import for {0} started at {1} and ended at {2}. It took {3} cycles and the elapsed time was {4}:{5}:{6}.", UserName, sTime, eTime, i, ts.Hours, ts.Minutes, ts.Seconds); 
         WriteToEventLog(msg, EventLogEntryType.Information); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
      finally 
      { 
       _isDequeueing = false; 
       WriteToEventLog("Exit DeQueue", EventLogEntryType.Information); 
      } 
     } 
     private void WriteToEventLog(Exception ex, EventLogEntryType eventLogEntryType) 
     { 
      try 
      { 
       string message = string.Empty; 
       string sTrace = ex.StackTrace; 
       while (ex != null) 
       { 
        message = message + Environment.NewLine + Environment.NewLine + ex.Message; 
        ex = ex.InnerException; 
       } 
       message = message + Environment.NewLine + Environment.NewLine + sTrace; 

       WriteToEventLog(message, eventLogEntryType); 
      } 
      catch (Exception ex2) 
      { 
       WriteToEventLog(ex2.Message, EventLogEntryType.Error); 
      } 
     } 
     private void WriteToEventLog(string message, EventLogEntryType eventLogEntryType) 
     { 
      try 
      { 
       this.EventLog.WriteEntry(message, eventLogEntryType); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 
     #endregion 
    } 
} 

2010-10-20 - NOTE - Ajout du fichier de code de service. Peut-être qu'il y a une erreur élémentaire ici?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Linq; 
using System.ServiceProcess; 
using System.Text; 
using System.IO; 
using sysIO = System.IO; 
using RivWorks.FeedHandler; 

namespace RivWorks.FeedHandler.Service 
{ 
    public partial class FeedListener : ServiceBase 
    { 
     #region Declarations 
     private List<string> _keys = new List<string>(); 
     private System.Threading.Timer _clock = null; 
     private FileSystemWatcher _watcher; 
     private BackgroundWorker _worker; 
     static private bool _isBusy = false; 
     #endregion 

     #region Constructor 
     public FeedListener() 
     { 
      InitializeComponent(); 
     } 
     #endregion 

     #region Start/Stop 
     protected override void OnStart(string[] args) 
     { 
      try 
      { 
       _keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" }); 

       _worker = new BackgroundWorker(); 
       _worker.WorkerReportsProgress = true; 
       _worker.WorkerSupportsCancellation = true; 
       _worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork); 
       _worker.ProgressChanged += new ProgressChangedEventHandler(BackgroundWorkerProgressChanged); 
       _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerRunWorkerCompleted); 

       _watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*"); 
       _watcher.IncludeSubdirectories = true; 
       _watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite; 
       _watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
       _watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
       _watcher.EnableRaisingEvents = true; 

       // check every 5 minutes... 
       _clock = new System.Threading.Timer(Tick, null, 0, 300000); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
       this.Stop(); 
      } 
     } 
     protected override void OnStop() 
     { 
      try 
      { 
       _watcher.Dispose(); 
       _watcher = null; 
       _clock.Dispose(); 
       _clock = null; 
       _worker.Dispose(); 
       _worker = null; 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Event Handlers 
     void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e) 
     { 
      try 
      { 
       DTO.BackgroundWorkerEventArgs eventArgs = new DTO.BackgroundWorkerEventArgs(); 
       sysIO.WatcherChangeTypes myType = e.ChangeType; 

       bool isValid = false; 
       foreach (string key in _keys) 
       { 
        if (Path.GetExtension(e.FullPath).Replace(".", "").Equals(key, StringComparison.CurrentCultureIgnoreCase)) 
         isValid = true; 
       } 

       if (isValid) 
       { 
        eventArgs.PathAndFile = e.FullPath; 
        eventArgs.Key = Path.GetExtension(e.FullPath).ToLower().Replace(".", ""); 
        eventArgs.FileName = Path.GetFileName(e.FullPath); 
        eventArgs.Path = Path.GetDirectoryName(e.FullPath); 
        eventArgs.UserName = Path.GetDirectoryName(e.FullPath).Replace(AppSettings.Default.FTPRootPath, "").Replace("\\", ""); 
        eventArgs.IsRunning = true; 

        System.Threading.Thread.Sleep(30000); 

        // Now, spin up a new thread and do the work on the file, based on file type... 
        _isBusy = true; 
        _worker.RunWorkerAsync(eventArgs); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) // 
        int i = 0; 
        DateTime sTime = DateTime.Now; 
        DateTime eTime = DateTime.Now; 
        while (_isBusy) 
        { 
         System.Threading.Thread.Sleep(5000); 
         i++; 
        } 
        eTime = DateTime.Now; 
        TimeSpan ts = new TimeSpan(eTime.Ticks - sTime.Ticks); 
        string msg = String.Format("Import for {0} started at {1} and ended at {2}. It took {3} cycles and the elapsed time was {4}:{5}:{6}.", eventArgs.UserName, sTime, eTime, i, ts.Hours, ts.Minutes, ts.Seconds); 
        WriteToEventLog(msg, EventLogEntryType.Information); 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Do work on another Thread 
     void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       RivWorks.FeedHandler.Handler handler = new RivWorks.FeedHandler.Handler(); 
       BackgroundWorker bw = sender as BackgroundWorker; 

       handler.Execute(bw, e); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
      finally 
      { 
       _isBusy = false; 
      } 
     } 
     void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      try 
      { 
       if (e.ProgressPercentage >= 100) 
       { 
        _isBusy = false; 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      try 
      { 
       if (e.Cancelled) 
       { 
        WriteToEventLog("Cancelled.", EventLogEntryType.Warning); 
        if (e.Error != null) 
        { 
         WriteToEventLog(e.Error, EventLogEntryType.Error); 
        } 
       } 
       else if (e.Error != null) 
       { 
        WriteToEventLog(e.Error, EventLogEntryType.Error); 
       } 
       else 
       { 
        WriteToEventLog("Successfully completed.", EventLogEntryType.Information); 
       } 
       _isBusy = false; 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 

     #region Private Methods 
     private void Tick(object data) 
     { 
      try 
      { 
       foreach (string key in _keys) 
       { 
        List<string> files = Directory.GetFiles(Path.Combine(AppSettings.Default.FTPRootPath), "*." + key, SearchOption.AllDirectories).ToList(); 
        foreach (string fileName in files) 
        { 
         System.Threading.Thread.Sleep(5000); 
         if (File.Exists(fileName)) 
         { 
          DateTime lat = File.GetLastWriteTime(fileName); 
          try 
          { 
           File.SetLastWriteTime(fileName, DateTime.Now); 
          } 
          catch 
          { 
           // just catch and ignore with a short pause... 
           System.Threading.Thread.Sleep(5000); 
          } 
         } 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     private void WriteToEventLog(Exception ex, EventLogEntryType eventLogEntryType) 
     { 
      try 
      { 
       string message = string.Empty; 
       string sTrace = ex.StackTrace; 
       while (ex != null) 
       { 
        message = message + Environment.NewLine + Environment.NewLine + ex.Message; 
        ex = ex.InnerException; 
       } 
       message = message + Environment.NewLine + Environment.NewLine + sTrace; 

       this.EventLog.WriteEntry(message, eventLogEntryType); 
      } 
      catch (Exception ex2) 
      { 
       WriteToEventLog(ex2, EventLogEntryType.Error); 
      } 
     } 
     private void WriteToEventLog(string message, EventLogEntryType eventLogEntryType) 
     { 
      try 
      { 
       this.EventLog.WriteEntry(message, eventLogEntryType); 
      } 
      catch (Exception ex) 
      { 
       WriteToEventLog(ex, EventLogEntryType.Error); 
      } 
     } 
     #endregion 
    } 
} 

Répondre

5

Même si elle est en cours d'exécution comme un exe de version, vous serez toujours donné la possibilité de joindre un débogueur lorsque les plantages d'applications ... vous ne pourrez pas voir les symboles de débogage, tout assemblage :)

Je crois que c'est le processus de Dr. Watson qui attrape les erreurs d'application pour le débogage ... Parce que votre application est un service, Dr. Watson ne peut pas interagir avec le bureau, vous donnant l'erreur que vous voyez. Vous pouvez aller dans les propriétés du service et marquer "Autoriser le service à interagir avec le bureau", qui se trouve dans l'onglet LogOn, qui devrait ensuite vous donner une fenêtre contextuelle Dr. Watson lorsque l'application se bloque.

étapes pour désactiver le Dr Watson sont ici:
http://support.microsoft.com/kb/188296

Si vous voulez déboguer l'application sur le serveur, vous pouvez activer le débogage à distance sur le serveur, et joindre Visual Studio au processus ... Si vous voulez essayer cela, je peux vous donner plus de conseils pour le débogage d'un service Windows à distance.

HTH, James


* Edit * Basé sur le code que vous avez fourni, je regarde les domaines suivants:

  1. est-AppSettings.Default.FTPRootPath correctement mis en App.Config?

  2. Des modifications sont-elles apportées à ce répertoire immédiatement au démarrage du service? Vous avez un chronomètre commenté comme "vérifier toutes les cinq minutes", ce qui est un peu déroutant, car le FileSystemWatcher commencera à recevoir des événements dès que vous définissez EnableRaisingEvents à true. Le problème peut donc se situer à l'intérieur fileCreatedOrChanged

  3. Dans ces lignes, vous avez un BackgroundWorker qui gère plusieurs événements, et pire, vous exécutez le gestionnaire de manière asynchrone. C'est mon suspect le plus probable, car si vous appelez de nouveau _worker.RunWorkerAsync() alors que le premier travail est en cours, vous obtiendrez un InvalidOperationException.Bien que je ne sache pas pourquoi vous ne le verriez pas dans le journal

  4. Vous utilisez la minuterie pour mettre à jour la dernière heure d'écriture pour tous les fichiers dans le répertoire surveillé, et vous le faites toutes les cinq secondes. Cela semble être une très mauvaise idée ... Je ne suis pas sûr de ce que vous essayez d'accomplir. Cela déclenchera l'événement modifié de votre FileSystemWatcher, ce qui expliquerait pourquoi vous plantez moins de 10 secondes après le démarrage (la coche initiale du chronomètre est définie pour se déclencher immédiatement, ce qui signifie cinq secondes plus tard que vous changez tous les temps de fichier, les FileSystemWatcher plusieurs fois peu de temps après)

donc ma meilleure estimation est que dans les cinq secondes, vous avez plusieurs tir cOMMENCÉ RunWorkAsync() appels sur le même BackgroundWorker, qui est un non-non:)

La définition de la variable statique _isBusy sur true/false n'est pas fiable car vous utilisez plusieurs threads avec BackgroundWorkers ... vous devez utiliser un Mutex moi autre serrure, mais cela ne va-t-il pas à l'encontre du but de l'utilisation de BackgroundWorker?

Aussi, si vous vouliez utiliser quelque chose comme un drapeau IsBusy, il devrait ressembler davantage:

while (_isBusy) { 
    System.Threading.Thread.Sleep(5000); 
} 

_isBusy = true; 
_worker.RunWorkerAsync(eventArgs); 

Vous devez _isBusy être faux avant d'essayer de lancer le travailleur de fond ... la comme vous l'avez, si l'événement se déclenche 100 fois, vous ferez 100 appels. La solution la plus simple à votre problème serait de créer un nouveau BackgroundWorker dans la méthode fileCreatedOrChanged à chaque fois que l'événement se déclenche ... il y a un surcoût impliqué dans la création de nouveaux threads, mais si le travail effectué dans cette méthode est significatif , ça vaudra le frais généraux. Vous pourriez être en mesure de compter sur la propriété BackgroundWorker.IsBusy intégrée, mais encore une fois, je devrais remettre en question l'avantage de threading asynchrone si vous allez juste bloquer jusqu'à ce que le travailleur de fond se termine.


** Modifier **

Je comprends maintenant ce que vous essayez d'accomplir avec les changements d'horodatage de fichier initial ... Je pense que vous feriez mieux de laisser les seuls horodatages, mais juste exécuter une boucle de démarrage pour traiter les fichiers existants. Vous pouvez générer un thread de travail d'arrière-plan pour chacun d'eux, comme vous le feriez sur les notifications FileSystemWatcher. La façon dont vous le manipulez crée délibérément un effet secondaire pour déclencher le résultat que vous voulez. Je perds un peu de la voie dans la complexité croissante ... toute la file d'attente/dequeue chose pourrait être inutile. Ou peut-être que je ne vois pas un besoin qui est vraiment là. Encore une fois, ce qui me frappe, c'est que vous lancez l'arrière-plan de manière asynchrone, puis mettez le thread principal en veille jusqu'à ce qu'il se termine. Lorsque vous mettez le thread principal en veille, aucun événement ne sera traité, donc vous limitez le multithreading à un thread. Je vois que vous voulez écrire dans le journal des événements combien de temps il a fallu pour terminer un thread. Je vais commencer une deuxième réponse pour répondre à cela si j'en ai l'occasion, mais l'essentiel est de passer une classe Stopwatch (qui vous donnera un compte précis des millisecondes ou des ticks CPU qui passent lors d'une opération) au DoWorkEventArgs Propriété .Result.

Mais le code que vous avez demandé! Fondamentalement, partout où vous décidez d'appeler _worker.RunWorkerAsync(queuedFile), plutôt que d'exécuter un niveau de classe BackgroundWorker créer un nouveau à chaque fois.Passez tous les mêmes paramètres pour les gestionnaires d'événements, etc. Votre point d'entrée de service baisserait toutes les références de BGW et ressembler à:

protected override void OnStart(string[] args) 
{ 
    try 
    { 
     _keys.AddRange(new string[] { "csv", "xml", "zip", "rivx" }); 

     _watcher = new FileSystemWatcher(AppSettings.Default.FTPRootPath, "*.*"); 
     _watcher.IncludeSubdirectories = true; 
     _watcher.NotifyFilter = sysIO.NotifyFilters.DirectoryName | sysIO.NotifyFilters.FileName | sysIO.NotifyFilters.LastAccess | sysIO.NotifyFilters.CreationTime | sysIO.NotifyFilters.LastWrite; 
     _watcher.Created += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
     _watcher.Changed += new sysIO.FileSystemEventHandler(fileCreatedOrChanged); 
     _watcher.EnableRaisingEvents = true; 

     WriteToEventLog("Exit Start", EventLogEntryType.Information); 
    } 

et le code où vous exécutez le BGW serait de manière asynchrone devenir:

BackgroundWorker worker = new BackgroundWorker(); 
worker.WorkerReportsProgress = true; 
worker.WorkerSupportsCancellation = true; 
worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork); 
worker.ProgressChanged += BackgroundWorkerProgressChanged;  // Note you don't need 
worker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted; // the 'new' here 

worker.RunWorkerAsync(queuedFile); // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) // 
+0

Merci pour l'information. J'ai beaucoup de gestion des erreurs via mon application et je m'attendais à écrire dans les journaux d'événements sur toutes les erreurs! C'est un serveur sans tête et n'a pas VS ou le débogage à distance installé (que je suis au courant de). Je suis probablement au point où je vais devoir essayer le débogage à distance bien que je doute que je puisse jamais attacher car le plus long il a couru est 9 secondes avant de sauter cette erreur de JIT. –

+0

L'utilisation de l'option "autoriser le service à interagir avec le bureau" n'a rien changé. Je vois toujours les 2 journaux d'événements (démarrage réussi et erreur de débogage JIT plus l'arrêt de l'événement). –

+0

Il y a une astuce que j'utilise pour déboguer un service ... dans le code de démarrage du service, j'écris while (true) {} comme première instruction. Ensuite, lorsque je me connecte au service, je peux faire une pause et mettre manuellement l'instruction suivante à la ligne suivante et déboguer à partir de là. Vous devrez augmenter considérablement le délai d'attente pour le service afin de vous donner le temps de le joindre. –

0

Le message d'erreur vous indique qu'il ne peut pas attacher un débogueur pour vous permettre d'inspecter l'exception. Ceci est complètement indépendant du fait qu'il s'agit d'une version release. Les versions de construction et de débogage de Release peuvent être déboguées (heureusement!).

Les services de débogage sont un peu différents du débogage des applications régulières. S'il vous plaît vérifier this guide pour quelques conseils.

+0

Merci pour l'info. J'ai vérifié le guide et essayé de faire comme il est dit. Malheureusement, le service ne fonctionne que quelques secondes avant de renflouer, donc je ne peux pas m'attacher. –

+0

@Keith: Avez-vous lu la partie sur la façon d'utiliser gflags pour démarrer le service avec le débogueur attaché? –

+0

Oui, je l'ai fait. Notre serveur n'est pas configuré pour le débogage à distance et je passe par la bureaucratie pour prouver qu'il ne détruira pas tout. Cependant, j'ai trouvé la cause du problème (voir les commentaires dans la réponse acceptée). –