Является ли асинхронная рекурсия безопасной в С# (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 ждет другого.
Кажется, что это нормально, поскольку раздел ожидания приведет к возврату кода вызывающему и, следовательно, не приведет к переполнению стека.
Итак, два вопроса:
-
если мы игнорируем тот факт, что мы имеем дело с сокетами в этом примере.
Это нормально, чтобы сделать стековую бесплатную рекурсию таким образом? или есть недостатки, которые я потерял?
-
с точки зрения ввода-вывода, будет ли вышеуказанный код достаточным для обработки всех входящих запросов?
Я имею в виду, просто ожидая его, и как только он будет принят, начните ждать другого.
Из-за этого некоторые запросы потерпят неудачу?
Ответы
Ответ 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...
}