当我希望我的异步方法不阻塞时,为什么Resharper坚持要添加等待?

时间:2013-04-22 03:25:46

标签: c# async-await

我正在尝试学习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告诉我,我应该将await添加到netClient.Start();,否则它不会阻止。但是,我不希望它阻止!

Resharper正在给我这样的警告这一事实让我想知道我是否错误地接近async/await系统。为什么Resharper希望我在此代码行中添加await,以及使用此代码的正确方法是什么,以便netClient.Start(); 阻止其他t​​cp连接加入?

2 个答案:

答案 0 :(得分:3)

  

然而,resharper告诉我,我应该添加等待netClient.Start();因为否则它不会阻止。但是,我不希望它阻止!

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

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

startTask = netClient.Start();

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

答案 1 :(得分:0)

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

此代码与“connect + fire并忘记处理数据的新线程”基本相同。

当您需要使用异步操作编写顺序代码时,

async / await会闪耀。在你的情况下,你真的需要并行操作 - 一些其他构造可能更好地启动多个侦听器。每个侦听器的代码都可能有利于使用await - 使用await read / await write更简单,而不是带有事件的多个状态(甚至更糟糕的是EndSend / SendReceive ...)。