异步/等待VS的BeginRead,EndRead [英] async / await vs BeginRead, EndRead

查看:203
本文介绍了异步/等待VS的BeginRead,EndRead的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不太'得到'异步和等待着呢,我在寻找一些澄清围绕一个特定的问题,我要解决的问题。基本上,我需要写一些code,它会处理TCP连接。这将基本上只是接收数据并进行处理,直到连接关闭。

我通常写使用的NetworkStream的BeginRead和EndRead这种模式code,但由于异步/的await模式是干净多了,我很想使用来代替。然而,由于我固然不完全理解到底是什么参与了这些,我是有点担心的后果。人会用比其他更多的资源;会不会有使用线程又在哪里会使用IOCP等。

费解的例子时间。这两个做同样的事情 - 在流数字节:

 类StreamCount
{
    私人流Str;
    私人诠释总= 0;
    私人字节[]缓冲区=新的字节[1000];    公共任务< INT> CountBytes(流Str)
    {
        this.str =海峡;        VAR TCS =新TaskCompletionSource< INT>();
        行动的onComplete =()=> tcs.SetResult(总);
        str.BeginRead(this.buffer,0,1000,this.BeginReadCallback,的onComplete);        返回tcs.Task;
    }    私人无效BeginReadCallback(IAsyncResult的AR)
    {
        VAR读取动作= str.EndRead(AR);
        如果(读取动作== 0)
        {
            ((动作)ar.AsyncState)();
        }
        其他
        {
            总+ =读取动作;
            str.BeginRead(this.buffer,0,1000,this.BeginReadCallback,ar.AsyncState);
        }
    }
}

...和...

 公共静态异步任务< INT> CountBytes(流Str)
    {
        VAR缓冲=新的字节[1000];
        无功总= 0;
        而(真)
        {
            INT读取动作=等待str.ReadAsync(缓冲,0,1000);
            如果(读取动作== 0)
            {
                打破;
            }
            总+ =读取动作;
        }
        总回报;
    }

我的眼睛,异步方式看起来更干净,但有是,而(真)循环,我没有受过教育的大脑告诉我将要使用一个额外的线程,更多的资源,因此不会扩展以及另一个。但我相当肯定是错误的。难道这些做同样的事情以同样的方式?


解决方案

  

我的眼睛,异步方式看起来更干净,但有是,而(真)循环,我没有受过教育的大脑告诉我将要使用一个额外的线程,更多的资源,因此不会扩展以及另一个


不,不会。循环将的只有的使用线程时,它的实际运行code ...只是因为它会在你的的BeginRead 回调。在等待前pression将返回控制到任何调用code是已经注册了该跳回在方法正确的地方延续(在适当的线程,基于同步上下文中),然后继续运行,直到它获取到方法的结尾或者碰到另一个的await 前pression。这正是你想要的:)

这是值得我们学习更多关于如何异步/等待幕后工作 - 你可能要开始与的它MSDN页面,作为一个跳点。

I don't quite 'get' async and await yet, and I'm looking for some clarification around a particular problem I'm about to solve. Basically, I need to write some code that'll handle a TCP connection. It'll essentially just receive data and process it until the connection is closed.

I'd normally write this code using the NetworkStream BeginRead and EndRead pattern, but since the async / await pattern is much cleaner, I'm tempted to use that instead. However, since I admittedly don't fully understand exactly what is involved in these, I'm a little wary of the consequences. Will one use more resources than the other; will one use a thread where another would use IOCP, etc.

Convoluted example time. These two do the same thing - count the bytes in a stream:

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

... And...

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

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. But I'm fairly sure that is wrong. Are these doing the same thing in the same way?

解决方案

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.

Nope, it won't. The loop will only use a thread when it's actually running code... just as it would in your BeginRead callback. The await expression will return control to whatever the calling code is, having registered a continuation which jumps back to the right place in the method (in an appropriate thread, based on the synchronization context) and then continues running until it either gets to the end of the method or hits another await expression. It's exactly what you want :)

It's worth learning more about how async/await works behind the scenes - you might want to start with the MSDN page on it, as a jumping off point.

这篇关于异步/等待VS的BeginRead,EndRead的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆