简体   繁体   English

是否应始终等待任务?

[英]Should Task always be Awaited?

I'm creating an asynchronous server that can have multiple clients. 我正在创建一个可以拥有多个客户端的异步服务器。 Similar to a chat client/server architecture, all clients are updated on each server state change based on any client's request. 与聊天客户端/服务器体系结构类似,所有客户端都会根据任何客户端的请求更新每个服务器状态更改。 I've found a lot of examples to follow and wrote a simple application for testing. 我发现了很多例子,并编写了一个简单的测试应用程序。 I've just written the processing of client requests for now but have come across a situation that I normally don't encounter. 我刚刚编写了客户端请求的处理,但遇到了我通常不会遇到的情况。 Here's the sample server I wrote: 这是我写的示例服务器:

class Server
{
    int _port;
    TcpListener _listener;
    IList<TcpClient> _clients = new List<TcpClient>();

    public Server(int port)
    {
        _port = port;
        _listener = new TcpListener(IPAddress.Any, _port);
    }

    public async Task StartListening()
    {
        _listener.Start();
        Console.WriteLine("The server is listening on port {0}...", _port);

        while (true)
        {
            try
            {
                var client = await _listener.AcceptTcpClientAsync();
                Console.WriteLine("We have a client!");
                _clients.Add(client);
                Process(client);

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

    private async Task Process(TcpClient client)
    {
        try
        {
            var stream = client.GetStream();
            var reader = new StreamReader(stream);
            var writer = new StreamWriter(stream) { AutoFlush = true };
            char[] buffer = new char[1024];
            while (true)
            {
                var request = await reader.ReadLineAsync();
                if (request != null)
                {
                    Console.WriteLine(request);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            client.Close();
        }
    }

}

Here's Program.cs: 这是Program.cs:

class Program
{
    static void Main(string[] args)
    {
        var server = new Server(6029);
        server.StartListening().Wait();
    }
}

I get a warning on the Process call since the Task isn't awaited. 因为没有等待任务,我在进程调用上收到警告。 I understand the behavior of the code without the await call but I'm wondering if I should be coding this differently (ThreadPool, etc...) even though this gives me the behavior that I want. 我理解没有await调用的代码的行为,但我想知道我是否应该以不同的方式编码(ThreadPool等等),即使这给了我想要的行为。 Should Tasks always be awaited? 是否应始终等待任务?

It's hard to know what you're really asking here. 很难知道你在这里问的是什么。 You have asked both the specific question implied by "I'm wondering if I should be coding this differently" , as well as the broad, primarily opinion-based question "Should Tasks always be awaited?" 您已经问过“我想知道我是否应该对此进行不同编码”所暗示的具体问题,以及广泛的,主要是基于意见的问题“应该始终等待任务吗?”

On the latter, the only answer that is conceivably correct is "no." 对于后者,唯一可以想象正确的答案是“不”。 There's practically nothing in programming that always has to be done. 有几乎没有什么编程中总是有许多工作要做。

That said, the code you posted certainly seems flawed. 也就是说,您发布的代码肯定存在缺陷。 For one, you have an async Task method that cannot ever possibly complete. 首先,您有一个无法完成的async Task方法。 What's the point of that? 那是什么意思? You might as well declare it async void . 您不妨将其声明为async void The program can just wait indefinitely via some other mechanism, like sleeping for an infinitely long time or blocking on a Console.ReadLine() method or something. 该程序可以通过其他一些机制无限期地等待,例如无限长时间的睡眠或者在Console.ReadLine()方法上阻塞等等。

Even better, give the program a way to shut itself down gracefully. 更好的是,给程序一个优雅地关闭自己的方法。 Close the listening socket when you want the server to stop listening. 如果希望服务器停止侦听,请关闭侦听套接字。 Store all the Task objects returned by Process() , and wait on them before allowing the process to complete, to ensure that your server gracefully closes the connections instead of forcefully resetting them. 存储Process()返回的所有Task对象,并在允许进程完成之前等待它们,以确保服务器正常关闭连接而不是强行重置它们。

The code you posted isn't really itself specific enough to provide anything specific in the way of advice. 您发布的代码实际上并不具体,无法提供任何具体的建议方式。 It looks like starter code, used mainly to demonstrate some basic concepts rather than to do anything real. 它看起来像初学者代码,主要用于演示一些基本概念,而不是做任何真实的事情。 As such, it's necessarily going to be subject to different rules than code that's supposed to work correctly in all situations. 因此,它必然会受到与在所有情况下应该正常工作的代码不同的规则的约束。


It seems to me that given your code example, I would await at some point the tasks you create. 在我看来,根据你的代码示例,我在某个时候等待你创建的任务。 You don't necessarily need to use await Process(...) (indeed, you probably don't want to, since that would prevent you from handling more than one client at a time), but you should keep the reference and wait eventually. 你不一定需要使用await Process(...) (事实上​​,你可能不想这样做,因为这会阻止你一次处理多个客户端),但你应该保留引用并等待最终。

But does that mean a Task must always be awaited? 但这是否意味着必须始终等待Task No. It just means in your example, you haven't shown a compelling reason not to. 不,这只是意味着在你的例子中,你没有表现出令人信服的理由。 In most cases, you should. 在大多数情况下,你应该。 If nothing else, it gives you the opportunity to observe any exception that might occur (speaking of which, you should not be catching Exception …catch only those exceptions which you expect and for which you know for sure how to handle). 如果没有别的,它让你有机会观察可能发生的任何异常(说到哪个,你不应该捕获Exception ......只捕获你期望的那些例外,你知道如何处理它们)。 But in rare cases, it can make sense to pay no attention to a task you've started, once it's started, if for no other reason than simply sheer practicality (or rather, the impracticality of trying to observe the task). 但是在极少数情况下,如果没有其他原因,除了简单的实用性(或者更确切地说,尝试观察任务的不切实际)之外,一旦启动任务,就不必关注你已经开始的任务。


Additional reading: 补充阅读:
How to safely call an async method in C# without await 如何在没有等待的情况下在C#中安全地调用异步方法
warning this call is not awaited, execution of the current method continues 警告不会等待此调用,继续执行当前方法
Where to stop using async /await keywords? 在哪里停止使用async / await关键字?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM