Служба Windows на основе C # запускается, а затем останавливается - почему? - PullRequest
1 голос
/ 18 октября 2010

Я создал службу Windows и по какой-то причине, когда я запускаю службу, она запускается, а затем снова выключается.Я пытался погуглить, почему это происходит.Ничего не появляется ни в каких системных журналах.Вот мой код запуска / остановки для сервиса.Я ожидаю, что поскольку я создал File Listener, он должен работать.Чего мне не хватает?

#region Declarations
private List<string> _keys = new List<string>();
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)
{
    _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;

    TouchFiles();
}
protected override void OnStop()
{
    _watcher.Dispose();
    _watcher = null;
    _worker.Dispose();
    _worker = null;
}
#endregion

#region Event Handlers
void fileCreatedOrChanged(object sender, sysIO.FileSystemEventArgs e)
{
    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)
    {
        try
        {
            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("\\", "");

            FileInfo fileInfo = new FileInfo(eventArgs.PathAndFile);

            // 1st attempt at stalling for the file lock due to slow write speeds...
            while (IsFileLocked(fileInfo)) { /* nop */ }

            // Wait until the thread is not busy...
            //while (_worker.IsBusy) { /* nop */ }
            while (_isBusy) { /* nop */ }

            // Now, spin up a new thread and do the work on the file, based on file type...
            _worker.RunWorkerAsync(eventArgs);  // goes to BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) //
        }
        catch (Exception ex)
        {
            string m = ex.Message;
        }
    }
}
void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
    DTO.BackgroundWorkerEventArgs eventArgs = (DTO.BackgroundWorkerEventArgs)e.Argument;
    RivWorks.FeedHandler.Handler handler = new RivWorks.FeedHandler.Handler();
    _isBusy = true;

    try
    {
        if (eventArgs.Key.Equals("csv", StringComparison.CurrentCultureIgnoreCase))
        {
            handler.ImportCSV(ref eventArgs);
        }
        if (eventArgs.Key.Equals("zip", StringComparison.CurrentCultureIgnoreCase))
        {
            handler.UnZip(ref eventArgs);
            handler.ImportCSV(ref eventArgs);
        }
    }
    catch (Exception ex)
    {
        string m = ex.Message;
        _worker.ReportProgress(0);
    }
    finally
    {
        _isBusy = false;
        _worker.ReportProgress(100);
        if (_worker.CancellationPending)
        {
            e.Cancel = true;
        }
    }
}
void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        Console.WriteLine("Cancelled.");
    }
    else if (e.Error != null)
    {
        Console.WriteLine(e.Error.Message);
    }
    else
    {
        Console.WriteLine("Successfully completed.");
    }

    TouchFiles();
}
#endregion

Ответы [ 8 ]

4 голосов
/ 18 октября 2010

Я не вижу код для TouchFiles (), но это похоже на источник проблемы.Например, когда он перебирает все каталоги на диске.Это занимает много времени, дольше, чем Service Control Manager готов мириться с тем, что служба запускается (думаю, 30 секунд).

Запустите поток и проследите, чтобы он касался файлов.Также остерегайтесь вашего BackgroundWorker, события не вызываются в том же потоке, который его запустил.Для этого требуется поставщик синхронизации, который недоступен в службе.

2 голосов
/ 18 октября 2010

Почему бы вам просто не отладить его?Добавьте Debugger.Break() в методе OnStart.

1 голос
/ 20 октября 2010

Я опубликовал ответ в другом, связанном с вами сообщении ... Я считаю, что проблема в том, что вы запускаете несколько вызовов RunWorkAsync на одном и том же BackgroundWorker, и это, вероятно, приводит к сбою службы.

Кроме того, вы используете флаг _isBusy в контексте многопоточных фоновых рабочих ... вам нужно использовать многопоточную систему блокировки, такую ​​как Mutex (хотя я все еще говорю, что побеждает точку запуска BackgroundWorkers асинхронно).

Проверьте ответ здесь: Служба Windows на основе C # - Пытается выполнить отладку JIT в рабочей среде

0 голосов
/ 19 октября 2010

Вы уверены, что используете правильный код запуска службы, сгенерированный для вас? Это может произойти, если он работает как приложение. У меня было такое, когда у меня есть отдельная функция Main (), которую я использую для тестирования.

0 голосов
/ 18 октября 2010

Похоже, что ваш OnStart просто запускается и завершается, вы не поддерживаете приложение живым, оно действует как консольное приложение, запускается, а затем завершается.Если это соответствует , вам нужно подождать чего-то вроде события службы завершения / завершения работы и позволить вашему рабочему фоновому потоку обрабатывать входящие рабочие запросы и не выходить из этой процедуры, пока ваше приложение не получит сигнал о завершенииот события, возможно.

0 голосов
/ 18 октября 2010

Попробуйте добавить строку Debugger.Launch() в начале вашего метода OnStart и переходите по этапам, пока не встретите исключение, вызывающее проблему.

С другой стороны, я бы реорганизовал дизайн так, чтобы основная часть работы была в отдельном и тестируемом классе, и просто подключил бы минимум к сервису.

0 голосов
/ 18 октября 2010

Я не знаю, что делает TouchFiles, но служба Windows обычно работает в цикле эквалайзера.while(true), что, похоже, не ваше.

0 голосов
/ 18 октября 2010

Может быть, вам нужно вызвать base.OnStart где-нибудь в OnStart?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...