Подтвердить что ты не робот

Является ли асинхронная рекурсия безопасной в С# (async ctp/.net 4.5)?

В С# с async ctp или бета-версией vs .net 2011 мы можем написать рекурсивный код следующим образом:

public async void AwaitSocket()
{
    var socket = await this.AcceptSocketAsync(); //await socket and >>return<< to caller
    AwaitSocket(); //recurse, note that the stack will never be deeper than 1 step since await returns..
    Handle(socket); // this will get called since "await" returns
}

В этом конкретном примере код async ожидает tcp-сокета, и как только он будет принят, он перезаписывает и async ждет другого.

Кажется, что это нормально, поскольку раздел ожидания приведет к возврату кода вызывающему и, следовательно, не приведет к переполнению стека.

Итак, два вопроса:

  • если мы игнорируем тот факт, что мы имеем дело с сокетами в этом примере. Это нормально, чтобы сделать стековую бесплатную рекурсию таким образом? или есть недостатки, которые я потерял?

  • с точки зрения ввода-вывода, будет ли вышеуказанный код достаточным для обработки всех входящих запросов? Я имею в виду, просто ожидая его, и как только он будет принят, начните ждать другого. Из-за этого некоторые запросы потерпят неудачу?

4b9b3361

Ответ 1

Из приведенного выше обсуждения, я думаю, что-то вроде этого будет лучшим подходом. Просьба дать отзыв

public async void StartAcceptingSockets()
{
    await Task.Yield(); 
    // return to caller so caller can start up other processes/agents
    // TaskEx.Yield in async ctp , Task.Yield in .net 4.5 beta

    while(true)
    {
        var socket = await this.AcceptSocketAsync();
        HandleAsync(socket); 
        //make handle call await Task.Yield to ensure the next socket is accepted as fast 
        //as possible and dont wait for the first socket to be completely handled
    } 
}

private async void HandleAsync(Socket socket)
{
      await Task.Yield(); // return to caller

      ... consume the socket here...
}