async / await vs BeginRead, EndRead

本文关键字:EndRead BeginRead vs await async | 更新日期: 2023-09-27 18:28:29

我还没有完全"获得"异步和等待,我正在寻找关于我将要解决的特定问题的澄清。基本上,我需要编写一些代码来处理TCP连接。它基本上只是接收数据并进行处理,直到连接关闭。

我通常会使用NetworkStream BeginRead和EndRead模式来编写这段代码,但由于async/await模式要干净得多,我很想使用它。然而,由于我不完全理解其中到底涉及到什么,我对后果有点担心。一个会比另一个使用更多的资源吗;一个线程将使用另一个线程使用IOCP等

卷积示例时间。这两个做相同的事情-计算流中的字节数:

class StreamCount
{
    private Stream str;
    private int total = 0;
    private byte[] buffer = new byte[1000];
    public Task<int> CountBytes(Stream str)
    {
        this.str = str;
        var tcs = new TaskCompletionSource<int>();
        Action onComplete = () => tcs.SetResult(total);
        str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete);
        return tcs.Task;
    }
    private void BeginReadCallback(IAsyncResult ar)
    {
        var bytesRead = str.EndRead(ar);
        if (bytesRead == 0)
        {
            ((Action)ar.AsyncState)();
        }
        else
        {
            total += bytesRead;
            str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState);
        }
    }
}

    public static async Task<int> CountBytes(Stream str)
    {
        var buffer = new byte[1000];
        var total = 0;
        while (true)
        {
            int bytesRead = await str.ReadAsync(buffer, 0, 1000);
            if (bytesRead == 0)
            {
                break;
            }
            total += bytesRead;
        }
        return total;
    }

在我看来,异步方式看起来更干净,但有一个"while(true)"循环,我未受过教育的大脑告诉我将使用额外的线程和更多的资源,因此不会像另一个那样扩展。但我确信这是错误的。这些人是以同样的方式做同样的事情吗?

async / await vs BeginRead, EndRead

在我看来,异步方式看起来更干净,但有一个"while(true)"循环,我未受过教育的大脑告诉我将使用额外的线程和更多的资源,因此不会像另一个那样扩展。

不,不会的。循环将只有在实际运行代码时才会使用线程。。。就像在BeginRead回调中一样。await表达式将控制权返回到调用代码的任何位置,注册了一个延续,该延续跳回到方法中的正确位置(在适当的线程中,基于同步上下文),然后继续运行,直到它到达方法的末尾或命中另一个await表达式。这正是你想要的:)

值得进一步了解异步/等待在幕后是如何工作的——您可能想从上面的MSDN页面开始,作为一个起点。