3

I am developing a windows service that is able to receive socket connection, so in the OnStart method:

protected override void OnStart(string[] args)
{
    start();
}

The start function looks like this:

public async void Start()
{
      //initialization things
      ...
      ...
      TcpListener listener = new TcpListener(IPAddress.Any, port);
      listener.Start();
      while(true)
      {
          TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
          ...
      }
      ...    
}

The problem is that no connection is accepted, while same code run perfect in standard command line project, I doubt there is a problem in my design, which thread runs the OnStart method?, when control goes back to OnStart after awaiting the accept process, is the async method ignored as it is a special case in windows service? Any suggestions is welcomed

ammcom
  • 992
  • 1
  • 7
  • 24
  • Most likely an uncaught exception caused your service to fail, because any exceptions will not be caught. Look into `Taskscheduler.UnobservedTaskException`, check your event log and refresh your services screen. https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=netframework-4.7.2 – Jesse de Wit Mar 05 '19 at 09:03
  • After checking event log, no unobserved exception there :( – ammcom Mar 05 '19 at 09:10
  • Change the signature of the method to `async Task`, and try again. – Jesse de Wit Mar 05 '19 at 09:17
  • Oh, and read this: https://stackoverflow.com/questions/6982294/why-doesnt-my-process-terminate-when-task-has-unhandled-exception – Jesse de Wit Mar 05 '19 at 09:22
  • A) don't use async void, B) log any unobserved exceptions, C) try running this in a console app before you commit to a service its easyer to debug, – TheGeneral Mar 05 '19 at 09:34

2 Answers2

7

When calling your start() method, the code instantly continues and OnStart completes. There is now no part of your own code that is able to catch any exceptions. Exceptions will have to be caught by the TaskScheduler. But this will only happen when the Task is awaited or garbage collected.

So basically, your code will have probably thrown an Exception that remains unobserved until the Task is garbage collected. In order to catch an log exceptions sooner, always make sure you catch exceptions inside the method that is not awaited anywhere:

protected override void OnStart(string[] args)
{
    Start();

    // This method finishes immediately (or at least after your first 
    // 'await' in the Start() method. That does not mean Start() runs 
    // on another thread however.
}

private async Task Start()
{
    try
    {
        //initialization things
        ...
        ...
        TcpListener listener = new TcpListener(IPAddress.Any, port);
        listener.Start();
        while(true)
        {
            TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
            ...
        }
        ...   
    }
    catch (Exception ex)
    {
        // TODO: LOG! And probably stop the service too.
    } 
}
Jesse de Wit
  • 3,867
  • 1
  • 20
  • 41
0

It seems it is a problem in Windows firewall, when I test my code as a console application, I had a confirmation message from Windows firewall to ask for permission to open the port, but when I test it as a service, firewall silently blocked the incoming connections without any notification.

ammcom
  • 992
  • 1
  • 7
  • 24