0

I created windows service. Installed with Installutil.exe success, but when i press start button appears progress bar "starting", then it stopped at 50 percent. I have to cancel. After cancel service works perfect, but start, stop and pasue commands disabled. If i want to stop service, i have to uninstall service. What can be reason ?

Main method:

static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
            { 
                new TelegramBotService()
            };
        ServiceBase.Run(ServicesToRun);
    }

It is my service class:

partial class TelegramBotService : ServiceBase
{
    private static Logger logger = LogManager.GetCurrentClassLogger();
    public TelegramBotService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        try
        {
            RunBot().Wait();
            logger.Info("Start windows service");
        }
        catch(Exception ex)
        {
            logger.Error(ex.Message);
        }
    }

    private async Task RunBot()
    {
        try
        {

          logger.Info("Start Telegram Bot");
          //var ElectionsBot = new ElectionsInfo();
          var ElectionsBot = new ElectionsCount();
          await ElectionsBot.Start();
        }
        catch(Exception ex)
        {
            logger.Error(ex.Message);
        }
    }

    protected override void OnStop()
    {
        logger.Info("Stop windows service");
    }
}
  • Does `ElectionsBot.Start()` ever return? – CodeCaster Feb 08 '16 at 11:14
  • No, Start() is "public async Task" method –  Feb 08 '16 at 11:18
  • Then see [Windows Service to run constantly](http://stackoverflow.com/questions/4864673/windows-service-to-run-constantly), where both your problem and various solutions are discussed. – CodeCaster Feb 08 '16 at 11:24
  • I don't believe this is a duplicate of the question specified by @CodeCaster. The question nominated by CodeCaster uses the [event-based asynchronous pattern](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/event-based-asynchronous-pattern-eap), whereas this question (and my answer) uses the more modern [task-based asynchronous pattern](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap). – HTTP 410 Nov 16 '19 at 17:34

1 Answers1

1

The OnStart method must finish within 10 seconds, otherwise the Service Control Manager thinks that it's hung. Currently it's waiting indefinitely for the RunBot task to finish.

I've described a good way to deal with this approach. This is my OnStart method, which launches the service's controller thread:

// SCM requests service start using its own thread.
// This method must complete within 10 seconds of it
// starting. Otherwise the SCM diagnoses a hang.
protected override void OnStart(string[] args)
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(this.UnhandledExceptionFilter);

    this.ThreadController = new Thread(new ThreadStart(ControllerThreadRunning));
    this.ThreadController.Name = THREAD_NAME_CONTROLLER;
    this.ThreadController.Start();
    base.OnStart(args);
}

This is the controller thread:

// Invoked when the controller thread starts. 
private void ControllerThreadRunning()
{
    // And we're on our way.
    while ( !this.ServiceStopRequested )
    {
        // Start real work and then block until that finishes or crashes.
        var realWork = this.LaunchWorkAsync();
        realWork.Wait();
        // If SCM didn't request a service stop, the assumption is that 
        // the real work crashed and needs to be restarted.
        if ( !this.ServiceStopRequested )
        {
            this.PauseControllerThread("Pause before restarting work cycle.", this.RestartDelay);
        }
    }

    // This service will now stop.
    this.Cleanup();
}

This asynchronously launches the service's real work:

// This method handles all ceremony around the real work of this service.
private async Task LaunchWorkAsync()
{
    try 
    {
        // Setup progress reporting.
        var progressReport = new Progress<string>
                (progressInfo => { this.AppLog.Information(progressInfo, "ServiceMain.LaunchWorkAsync"); });
        var progress = progressReport as IProgress<string>;
        // Launch time.
        await Task.Factory.StartNew( () => this.DoWork(progress), TaskCreationOptions.LongRunning );
    }

    // Report any exception raised during the work cycle.
    catch (Exception ex)
    {
        this.AppLog.Error(string.Concat("Work cycle crashed", Environment.NewLine,
                                         ex.GetType().FullName, Environment.NewLine,
                                         ex.Message, Environment.NewLine,
                                         ex.StackTrace));
    }

    return;
}

And this is where the service's real work is done:

// This is where this service's real work is done.
// The work cycles continuously until it's asked to stop.
// If the work crashes with an unhandled exception, the 
// controller thread will restart it after an appropriate delay.
private void DoWork(IProgress<string> progress)
{
    while (!this.ServiceStopRequested)
    {
        Thread.Sleep(5000);     // Simulated work cycle.
        progress.Report("Completed current cycle of work.");
    }
}
HTTP 410
  • 17,300
  • 12
  • 76
  • 127
  • Apart from this question being a duplicate, please include the relevant content from that link or leave it out altogether. – CodeCaster Feb 08 '16 at 11:23
  • 1
    I've added the relevant code. The OP's question uses the async/await pattern, as does my answer. – HTTP 410 Feb 08 '16 at 11:45