Chris Schiffhauer
Chris Schiffhauer

Reputation: 17290

TcpListener.AcceptSocket() fails in a Windows Service

I have an instance of the following code that executes correctly in Debug or as a standalone Windows application:

TcpListener tcpListener = new TcpListener(IPAddress.Any, 4554);
tcpListener.Start();

while (true)
{
    try
    {
        using (Socket socket = tcpListener.AcceptSocket())
        {
            // Code here is reached in Debug or as a Console Application
            // but not as a Windows Service
        }
    }
    catch (SocketException se)
    {
        // This is never reached
    }
    catch (Exception ex)
    {
        // This is never reached
    }
    finally
    {
        // This is never reached in the Windows Service
    }
}

However, when I install it as a Windows Service, it crashes on tcpListener.AcceptSocket(), and logs the following to the Event Viewer:

An unhandled exception ('System.Net.Sockets.SocketException') occurred in MyService.exe [768]. Just-In-Time debugging this exception failed with the following error: The operation attempted is not supported.

Even trying to catch the exception I am unable to log anything more. Stepping through code in Debug accomplishes nothing because the code successfully blocks the application and waits for a client connection.

Is there a way to implement this for a Windows Service?

Upvotes: 1

Views: 1322

Answers (1)

Chris Schiffhauer
Chris Schiffhauer

Reputation: 17290

usr's advice (and this answer) led me to a bug in the code. The ServiceBase class contained the following:

protected override void OnStart(string[] args)
{
    _worker = new Thread(ExecuteService);
    _worker.Start();
}

private void ExecuteService()
{
    for (;;)
    {
         if (_stop.WaitOne(1000))
        {
            new TcpServer().StartTcpServer();
            return;
        }
    }
}

The correct implementation was to remove the for loop, which was re-instantiating the listener. Here is the final code:

protected override void OnStart(string[] args)
{
    _worker = new Thread(ExecuteService);
    _worker.Start();
}

private static void ExecuteService()
{
    new TcpServer().StartTcpServer();
}

Upvotes: 1

Related Questions