簡體   English   中英

是否建議/可以在新線程中運行異步void方法?

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

我有一段舊代碼(.NET 3.5),我在一個單獨的線程中運行新TcpClient的注冊:

舊代碼:

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

此代碼的目的是避免在等待新客戶端時阻止應用程序。 我正在將此代碼移植到.NET Standard,我想知道是否必須使用.NET的新功能。

我說的是async/awaitTask

異步線程版本

由於此線程將與整個應用程序一樣長,因此我首先考慮用新的異步方法簡單地替換實際方法。 但是,如果這樣做,我最終會得到一個運行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
        }
    }
}

除極少數情況(如事件處理程序)外,不建議編寫async void方法。

這種情況可以接受嗎?

異步任務版本

作為一個新選項,我在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
        }
    }
}

使用此代碼,只要我不await AcceptConnectionsAsync調用,就不會阻止該應用程序(我使用while(true)簡化了代碼,但是我處理了該應用程序的關閉操作並正確地結束了監聽,我可以調用等待那里,甚至開火就算了)。

但是正如我所說,該操作應該持續整個應用程序的時間,我認為一個新線程更合適(至少在體系結構方面,但在效率方面)。

我錯了嗎?

不要對代碼的這一部分進行任何更改

這是我看到的最后一個選項。 我打算用Async/Await Await更新代碼,因為我讀到async / await可以提高TcpListener的性能。

但這是真的嗎?

重要信息

以下是一些我認為可能相關的信息。 不要猶豫,要求進一步的細節。

  • 運行此代碼的應用程序是控制台應用程序。 我知道這對於異步/等待上下文可能很重要?
  • AcceptConnections(Async)方法為每個新的連接運行一個新的Task(這些任務是短暫的,類型為即發即忘)。
  • 主線程執行大量計算。 最好的解決方案是對主線程性能的影響最小。
  • 還有一個線程的行為與此相同(持續時間相同),負責偵聽來自所有客戶端的數據。 我打算應用與此操作相同的操作。

但是正如我所說,此操作應該持續到整個應用程序

不,不是。 該方法幾乎立即返回。 這就是異步方法的含義 工作完成時,它不會阻止呼叫者。

創建一個僅用於調用異步方法的新線程就像雇用某人來您家為您的信箱中放入一封信一樣。 它比您自己完成更多的工作,因為將信件發送到目的地的實際行為實際上並不會阻止您僅進行一些瑣碎的工作即可開始工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM