基于C#的Windows服务启动然后停止 - 为什么?

时间:2010-10-18 17:39:23

标签: c# windows-services

我已经构建了Windows服务,出于某种原因,当我启动服务时,它会启动,然后立即关闭。我试过谷歌搜索为什么会发生这种情况。任何系统日志中都没有出现任何内容。这是我的服务的开始/停止代码。我希望,因为我已经创建了一个文件监听器,它应该保持运行。我错过了什么?

#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 个答案:

答案 0 :(得分:4)

我没有看到TouchFiles()的代码,但它听起来像是问题的根源。就像它迭代磁盘驱动器上的所有目录一样。这需要花费很多时间,然后服务控制管理员愿意忍受服务开始(我想30秒)。

启动一个帖子并让它触摸文件。还要注意你的BackgroundWorker,事件是在启动它的同一个线程上调用而不是。这需要一个服务中不可用的同步提供程序。

答案 1 :(得分:2)

为什么不调试它?在Debugger.Break()方法中添加OnStart

答案 2 :(得分:1)

我在您的其他相关帖子中发布了一个答案...我认为问题是您在同一个BackgroundWorker上发起多个RunWorkAsync来电,这可能会导致该服务崩溃。

此外,您在多线程后台工作程序的上下文中使用_isBusy标志...您需要使用多线程锁定系统,例如Mutex(尽管我仍然说这会破坏运行点BackgroundWorkers异步)。

在此处查看答案:C# based Windows Service - Tries to do JIT Debugging in production

答案 3 :(得分:0)

也许你需要在OnStart的某个地方调用base.OnStart吗?

答案 4 :(得分:0)

我不知道TouchFiles的作用,但是Windows服务通常在循环eq中运行。 while(true),你的似乎没有。

答案 5 :(得分:0)

尝试在OnStart方法的开头添加Debugger.Launch()行并逐步执行,直到遇到导致问题的异常为止。

另一方面,我会重构设计,因此大部分工作都在一个单独的可测试的类中,只需将服务中的最小部分连接起来。

答案 6 :(得分:0)

看起来你的OnStart只是执行和退出,你没有保持应用程序活着,它就像一个控制台应用程序,开始运行然后退出。如果 这种情况,您需要等待结束/关闭服务事件之类的事情,并让您的工作人员后台线程处理传入的工作请求,而不是退出此例程,直到您的应用程序收到信号通知终止,或许来自一个事件。

答案 7 :(得分:0)

您确定使用的是为您生成的正确服务启动代码吗?如果它只是作为应用程序运行,可能会发生这种情况。当我有一个单独的Main()用于测试时,我发生了这种情况。