async/await vs BeginRead,EndRead

Bar*_*ast 6 c# asynchronous networkstream async-await

我还没有"得到"异步并等待,我正在寻找一些关于我即将解决的特定问题的澄清.基本上,我需要编写一些能够处理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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

......而且......

    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;
    }
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 8

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

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

值得进一步了解async/await如何在幕后工作 - 您可能希望从它上面的MSDN页面开始,作为跳跃点.