0

我正在努力学习async/await,所以这听起来像是一个愚蠢的问题,但我目前正在开发一个基本的 TCP 服务器,并尝试使用async/await而不是手动线程来处理多个连接。

在一个NetworkClient类中,我有以下方法:

    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;
                }
            }
        }
    }

我的侦听客户端连接的循环包含以下代码:

    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++;
        }
    }

这可以按我的预期工作,允许多个 telnet 连接同时连接并向服务器发送消息。但是,resharper 告诉我应该添加awaitnetClient.Start();否则它不会阻塞。但是,我不想让它阻塞!

Resharper 给我这样的警告的事实让我怀疑我是否async/await错误地接近系统。为什么 Resharper 要我添加await到这行代码中,以及使用此代码的正确方法是什么,这样不会netClient.Start();阻止其他 tcp 连接加入?

4

2 回答 2

4

但是,resharper 告诉我应该将 await 添加到 netClient.Start(); 因为否则它不会阻塞。但是,我不想让它阻塞!

ReSharper 会对这种情况发出警告,因为它通常是一个错误。

在您的情况下,您可以在您的类型中创建一个private Task代表该Start方法的成员并分配它而不是await它:

startTask = netClient.Start();

这应该避免警告,并使您能够确定Start方法何时退出并检测它抛出的任何异常。

于 2013-04-22T17:44:18.730 回答
0

Start的方法并不是真正的异步 - 看起来它等待连接同步发生,而不是异步读取数据。结果,您的代码实际上确实按照您期望的方式工作 -之前完成ListenForClients的同步部分(因此它打印正确的文本),而不是异步部分将自行运行而无需任何人等待结果。StartConsole.WriteLine

此代码本质上与“连接 + 触发并忘记新线程来处理读取数据”相同。

async/await当您需要使用异步操作编写顺序代码时闪耀。在您的情况下,您确实需要并行操作-启动多个侦听器可能会更好。使用每个侦听器的代码可能会受益await- 在循环中使用等待读取/等待写入要简单得多,而不是带有事件的多个状态(或者更糟糕的是 EndSend/SendReceive...)。

于 2013-04-22T04:02:28.457 回答