简体   繁体   English

是否建议/可以在新线程中运行异步void方法?

[英]Is it recommended/acceptable to run an async void method into a new thread?

I have an old piece of code (.NET 3.5) where I run in a separate thread the registration of new TcpClient: 我有一段旧代码(.NET 3.5),我在一个单独的线程中运行新TcpClient的注册:

Old code: 旧代码:

public class TcpServer
{
    private readonly TcpListener _tcpListener;

    public TcpServer(int port)
    {
        _tcpListener = new TcpListener(IPAddress.Any, port);
    }

    public void StartListening()
    {
        _tcpListener.Start();

        var t = new Thread(new ThreadStart(AcceptConnections));
        t.Start();
    }

    private void AcceptConnections()
    {
        while (true)
        {
            var client = _tcpListener.AcceptTcpClient();

            // Some stuff
        }
    }
}

The goal of this code is to avoid blocking the app while waiting for new clients. 此代码的目的是避免在等待新客户端时阻止应用程序。 I am porting this code to .NET Standard and I wonder whether I have to use the new features of .NET. 我正在将此代码移植到.NET Standard,我想知道是否必须使用.NET的新功能。

I am talking about async/await and Task . 我说的是async/awaitTask

Async Thread version 异步线程版本

Since this thread will last as long as the whole application, I first considered to simply replace the actual method by the new asynchronous one. 由于此线程将与整个应用程序一样长,因此我首先考虑用新的异步方法简单地替换实际方法。 But if I do so, I end up with a new thread running an async void method: 但是,如果这样做,我最终会得到一个运行async void方法的新线程:

public class TcpServer
{
    private readonly TcpListener _tcpListener;

    public TcpServer(int port)
    {
        _tcpListener = new TcpListener(IPAddress.Any, port);
    }

    public void StartListening()
    {
        _tcpListener.Start();

        var t = new Thread(new ThreadStart(AcceptConnectionsAsync));
        t.Start();
    }

    private async void AcceptConnectionsAsync()
    {
        while (true)
        {
            var client = await _tcpListener.AcceptTcpClientAsync();

            // Some stuff
        }
    }
}

It is not recommended to write async void method except in rare case (like event handler). 除极少数情况(如事件处理程序)外,不建议编写async void方法。

Is this case acceptable? 这种情况可以接受吗?

Async task version 异步任务版本

As a new option, I run the registration in a Task : 作为一个新选项,我在Task运行注册:

public class TcpServer
{
    private readonly TcpListener _tcpListener;

    public TcpServer(int port)
    {
        _tcpListener = new TcpListener(IPAddress.Any, port);
    }

    public Task StartListeningAsync()
    {
        _tcpListener.Start();

        return Task.Run(async () => await AcceptConnectionsAsync());
    }

    private async Task AcceptConnectionsAsync()
    {
        while (true)
        {
            var client = await _tcpListener.AcceptTcpClientAsync();

            // Some stuff
        }
    }
}

With this code, as long as I do not await the AcceptConnectionsAsync call, the app is not blocked (I simplify the code with a while(true) but I handle the closure of the app and the end of the listening properly, I can call the await there or even fire-and-forget it). 使用此代码,只要我不await AcceptConnectionsAsync调用,就不会阻止该应用程序(我使用while(true)简化了代码,但是我处理了该应用程序的关闭操作并正确地结束了监听,我可以调用等待那里,甚至开火就算了)。

But as I said, this action is supposed to last as long as the whole application, I think a new thread is more appropriate (in term of architecture at least but also in term of efficiency). 但是正如我所说,该操作应该持续整个应用程序的时间,我认为一个新线程更合适(至少在体系结构方面,但在效率方面)。

Am I wrong? 我错了吗?

Do not change anything to this part of the code 不要对代码的这一部分进行任何更改

This is the last option I see. 这是我看到的最后一个选项。 I intended to update the code with the Async/Await because I read that the async/await improves the performance of the TcpListener. 我打算用Async/Await Await更新代码,因为我读到async / await可以提高TcpListener的性能。

But is that true? 但这是真的吗?

Important information 重要信息

Here are some information I think can be relevant. 以下是一些我认为可能相关的信息。 Do not hesite to ask for further details. 不要犹豫,要求进一步的细节。

  • The application running this code is a Console App. 运行此代码的应用程序是控制台应用程序。 I know this can be important regarding to async/await context? 我知道这对于异步/等待上下文可能很重要?
  • The AcceptConnections(Async) method runs a new Task for each new connection (these tasks are short-lived and of type fire-and-forget). AcceptConnections(Async)方法为每个新的连接运行一个新的Task(这些任务是短暂的,类型为即发即忘)。
  • The main thread performs huge calculations. 主线程执行大量计算。 The best solution is the least impacting regarding to the main thread performance. 最好的解决方案是对主线程性能的影响最小。
  • There is one other thread that behave like this one (same duration), responsible for listening the data coming from all clients. 还有一个线程的行为与此相同(持续时间相同),负责侦听来自所有客户端的数据。 I intend to apply the same operations as this one. 我打算应用与此操作相同的操作。

But as I said, this action is supposed to last as long as the whole application 但是正如我所说,此操作应该持续到整个应用程序

No, it doesn't. 不,不是。 The method will return almost immediately. 该方法几乎立即返回。 That's what it means for a method to be asynchronous. 这就是异步方法的含义 It doesn't block the caller while the work is being done. 工作完成时,它不会阻止呼叫者。

Creating a new thread just to call an asynchronous method is like hiring someone to come to your house to put a letter in your mailbox for you. 创建一个仅用于调用异步方法的新线程就像雇用某人来您家为您的信箱中放入一封信一样。 It's more work than just doing it yourself, because the actual act of getting the letter to its destination doesn't actually prevent you from doing work outside of a trivial bit of work to just get it started. 它比您自己完成更多的工作,因为将信件发送到目的地的实际行为实际上并不会阻止您仅进行一些琐碎的工作即可开始工作。

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

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