c# - 异步/等待 vs BeginRead、EndRead

标签 c# asynchronous async-await 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);
        }
    }
}

……还有……

    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)”循环将使用额外的线程、更多资源,因此不会像以前那样扩展另一个。但我相当确定那是错误的。这些是否以相同的方式做相同的事情?

最佳答案

To my eyes, the async way looks cleaner, but there is that 'while (true)' loop that my uneducated brain tells me is going to use an extra thread, more resources, and therefore won't scale as well as the other one.

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

值得了解更多有关 async/await 在幕后如何工作的信息 - 您可能想从 the MSDN page on it 开始, 作为一个起点。

关于c# - 异步/等待 vs BeginRead、EndRead,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26652328/

相关文章:

c# - 从此代码片段中删除重复项

javascript - 如何使 jquery CSS 操作同步(即没有回调)?

c# - 处理 Task.Run 中的异常

wcf - 在 CaSTLe.Windsor 中将客户端基于任务的操作与 WCFFacility 结合使用

c# - System.Reflection.Assembly 不包含 'GetExecutingAssembly' 的定义

c# - 通过 .net 应用程序将报告文件上传到报告管理器?

c# - WPF 页面之间的切换

asynchronous - Go队列处理失败重试

async-await - AXIOS 请求 : "Error: connect ECONNREFUSED 127.0.0.1:80"

c# - CreateLinkedTokenSource 抛出 ObjectDisposedException。如何正确安全地处置 CancellationTokenSource?