首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步ctp递归

异步ctp递归
EN

Stack Overflow用户
提问于 2011-06-23 07:11:34
回答 1查看 686关注 0票数 5

我和async CTP的第一场比赛已经进行了15分钟……(很好)。

这是我拼凑的一个非常简单的服务器:

代码语言:javascript
复制
internal class Server
{
    private HttpListener listener;
    public Server()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://*:80/asynctest/");
        listener.Start();
        Go();
    }

    async void Go()
    {
        HttpListenerContext context = await listener.GetContextAsync();
        Go();
        using (var httpListenerResponse = context.Response) 
        using (var outputStream = httpListenerResponse.OutputStream) 
        using (var sw = new StreamWriter(outputStream))
        {
            await sw.WriteAsync("hello world");
        }
    }
}

可以看出,异步方法Go调用自身。在传统的非异步环境中,这将导致堆栈溢出。我假设异步方法不是这样的,但我想确认一下,不管是哪种方式。有没有人?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-23 11:24:07

让我们把它分解成更简单的东西:

代码语言:javascript
复制
async static void Go()
{
    await Something();
    Go();
    await SomethingElse();
}

编译器是如何处理这个问题的?

基本上,这变成了类似于下面的草图:

代码语言:javascript
复制
class HelperClass
{
    private State state = STARTSTATE;
    public void DoIt()
    {

        if (state == STARTSTATE) goto START;
        if (state == AFTERSOMETHINGSTATE) goto AFTERSOMETHING;
        if (state == AFTERSOMETHINGELSESTATE) goto AFTERSOMETHINGELSE;

        START:
        {
           state = AFTERSOMETHINGSTATE;
           var awaiter = Something().MakeAnAwaiter();
           awaiter.WhenDoneDo(DoIt);
           return;
        }

        AFTERSOMETHING:
        {
           Go();
           state = AFTERSOMETHINGELSESTATE;
           var awaiter = SomethingElse().MakeAnAwaiter();
           awaiter.WhenDoneDo(DoIt);
           return;
        }

        AFTERSOMETHINGELSE:

        return;
    }

    static void Go()
    {
        var helper = new HelperClass();
        helper.DoIt();
    }

现在,您需要记住的是,当每个异步操作完成时,消息循环将再次调用"DoIt“(当然是在帮助器的适当实例上)。

那么会发生什么呢?把它弄清楚。你第一次调用Go。这使得帮助器成为第一个,并调用DoIt。这将调用某个(),获取一个任务,为该任务创建一个等待器,告诉该等待器“完成后,调用helper1.DoIt”,然后返回。

十分之一秒后,任务完成,消息循环调用helper1的DoIt。Helper1的状态是AFTERSOMETHINGSTATE,所以我们获取goto并调用Go。这将生成helper2并对其调用DoIt。这将调用Something(),获取一个任务,为该任务创建一个等待器,告诉该等待器“完成后,在helper2上调用DoIt”,并将控制权返回给helper1的DoIt。它调用SomethingElse,为该任务创建一个等待器,并告诉它“当你做完其他事情时,调用helper1的DoIt”。然后它会返回。

现在我们有两个未完成的任务,堆栈上没有代码。其中一项任务将首先完成。假设SomethingElse任务首先完成。消息循环调用helper1.DoIt(),该函数立即返回。Helper1现在是垃圾了。

稍后,消息循环调用helper2.DoIt(),并转移到AFTERSOMETHING。现在调用Go(),它创建了helper3...

所以不,这里没有无限的递归。每次Go执行时,它都会异步启动某个东西(),然后返回给调用者。对"something“之后的东西的调用稍后会发生。"Go“一次只能在堆栈上出现一次。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6447626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档