0

I am writing a socket server and trying to leverage the new async / await features.

I've based my code off this stackoverflow answer

I get

An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll

Is there anything obvious anyone can see in the below code?

public void Main()
{          
    CancellationTokenSource cts = new CancellationTokenSource();
    TcpListener listener = new TcpListener(IPAddress.Any, 6666);

    listener.Start();

    while (true)
    {
        AcceptClientsAsync(listener, cts.Token);
    }

    cts.Cancel();
    listener.Stop();
}

async Task AcceptClientsAsync(TcpListener listener, CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        TcpClient client = await listener.AcceptTcpClientAsync();
        Console.WriteLine("Client. Doing the do.");
        SomeTaskAsync(client, ct);
    }

}

async Task SomeTaskAsync(TcpClient client, CancellationToken ct)
{
    var stream = client.GetStream();

    while (!ct.IsCancellationRequested)
    {
        // Do Stuff

        stream.Close();
        client.Close();
    }
}
Community
  • 1
  • 1
Sam Leach
  • 12,746
  • 9
  • 45
  • 73

1 Answers1

1

The original code had a sleep:

try
{
    listener.Start();
    AcceptClientsAsync(listener, cts.Token);
    Thread.Sleep(60000);
}

where you have an infinite busy loop:

while (true)
{
    AcceptClientsAsync(listener, cts.Token);
}

You cannot do this in an async await pattern, your call to AcceptClientsAsync returns immediately and you end up with a busy infinite loop. No wonder you hit OOM.

Have a look at Asynchronous Server Socket Example and see how the listening loop is waiting on an event inside the loop. You must do something similar. For example you can have new listeners submitted when one completes (accepts). Your main must either wait, or better still use an appropriate template for a server: a service process, for education. For real world use let the framework do the heavy listing for you, eg. WCF.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • Thanks for your answer. Should I be using the async await pattern in my case? The aim would be to simplify the code. – Sam Leach Jul 23 '13 at 12:23
  • Yes, async await is still great. The async example from the MSDN sample can easily be ported to async await. Better still, I'm sure there is a async await specific sample out there. – Remus Rusanu Jul 23 '13 at 12:57
  • You'd think there would be an example, but so far, I cannot find one. – Sam Leach Jul 23 '13 at 13:12
  • See [this MSDN Forum thread](http://social.msdn.microsoft.com/Forums/en-US/aac79f64-5886-40f5-a8f1-a4a6f2460c85/converting-microsofts-asynchronous-server-socket-sample-to-async-ctp). – Remus Rusanu Jul 23 '13 at 15:01