0

This question already has an answer here:

I am trying to learn async/await so this may sound like a dumb question, but I am currently working on a basic TCP server and trying to use async/await instead of manual threading to handle multiple connections.

In a NetworkClient class I have the following method:

    public async Task Start()
    {
        using (var reader = new StreamReader(_socket.GetStream()))
        {
            while (_server.IsRunning)
            {
                try
                {
                    var content = await reader.ReadLineAsync().ConfigureAwait(false);
                    if (content == null)
                    {
                        Console.WriteLine("Client {0} disconnected", _id);
                        return;
                    }

                    Console.WriteLine("Client {0} wrote: {1}", _id, content);
                }
                catch (IOException)
                {
                    Console.WriteLine("Client {0} disconnected", _id);
                    return;
                }
            }
        }
    }

My loop that listens for client connections contains the following code:

    private void ListenForClients()
    {
        var numClients = 0;
        while (IsRunning)
        {
            var tcpClient = _listener.AcceptTcpClient();
            var netClient = new NetworkClient(this, tcpClient, numClients);
            netClient.Start();

            Console.WriteLine("Client {0} Connected", numClients);
            numClients++;
        }
    }

This works as I expect it, allowing multiple telnet connections to connect and send messages to the server at the same time. However, resharper tells me that I should be adding await to netClient.Start(); because otherwise it won't block. However, I do not want it to block!

The fact that Resharper is giving me a warning like this makes me wonder if I am approaching the async/await system incorrectly. Why does Resharper want me to add await to this line of code, and what is the correct way to work with this so that netClient.Start(); does not block other tcp connections from joining?


2 답변


3

However, resharper tells me that I should be adding await to netClient.Start(); because otherwise it won't block. However, I do not want it to block!

ReSharper will warn about this situation because it's usually an error.

In your case, you can create a private Task member in your type that represents the Start method and assign it rather than await it:

startTask = netClient.Start();

This should avoid the warning, and give you the ability to determine when the Start method exits and detect any exceptions it throws.


0

You Start method is not really asynchronous - it looks like it waits for connection to happen synchronously and than asynchronously reads data. As result your code in ListenForClients actually does work the way you expect - synchronous part of Start finishes before Console.WriteLine (so it prints correct text) and than asynchronous part will run by itself without anyone waiting for result.

This code is essentially the same as "connect + fire and forget new thread to handle reading the data".

async/await shine when you need to write sequential code with asynchronous operations. In you case you really need parallel operations - some other construct would be probably better to starting multiple listeners. Code for each listener will likely benefit of using await - much simpler to use await read/await write in a loop instead of multiple states with events (or even worse EndSend/SendReceive...).


  • I'm not sure i understand. My Start method is meant to look for clients synchronously, but once a client is connected it needs to asynchronously wait for data for that client. That's what I have and that works. The problem is resharper wants me to await netClient.Start(); which would then cause it to synchronously block when waiting for new input from clients and never accept any new tcp clients - KallDrexx
  • @KallDrexx By not awiat-ing async function you are writing code that looks broken - you'd have to put half page comment in code explaining why it is OK. Try to split Start into 2 functions and explicitly kick of reading on new thread. Note: I think you use "synchronously" in 2 meanings - one "blocking wait on current thread" (how first part of Start behaves) and another "code in my function will not move past that point till operation is done potentially not blocking the thread" (how await behaves). - Alexei Levenkov

Linked


Related

Latest