Продолжения с использованием Async CTP - PullRequest
1 голос
/ 14 апреля 2011

Можно ли использовать Async CTP для эмуляции продолжений и хвостовой рекурсии?

Я думаю о чем-то вроде:

async Task Loop(int count)
{
    if (count == 0)
        retrun;

    await ClearCallStack();
    //is it possible to continue here with a clean call stack?
    Loop(count -1)
}

Полагаю, нужен индивидуальный планировщик и тому подобное, но возможно ли это? (то есть может ли он использоваться для рекурсии без перебора стека вызовов)

1 Ответ

4 голосов
/ 15 апреля 2011

Да, это вполне возможно.

В новейшем асинхронном CTP (обновление для VS2010 SP1) в образце модульного тестирования есть класс GeneralThreadAffineContext (либо в VB, либо в C #). Это обеспечивает необходимый вспомогательный код для простого запуска асинхронного метода общего назначения для потоков.

Под сходством потоков мы подразумеваем, что асинхронные продолжения обрабатываются в том же контексте, что и исходный поток, аналогично поведению для WinForms / WPF, но без раскручивания реального цикла сообщений WPF или WinForms.

Дизайн

Task.Yield() состоит в том, чтобы отложить остаток текущего метода до SynchronizationContext, так что вам даже не нужно писать свой собственный await ClearCallStack(). Вместо этого ваш образец будет сводиться к:

async Task DoLoop(int count)
{
    // yield first if you want to ensure your entire body is in a continuation
    // Final method will be off of Task, but you need to use TaskEx for the CTP
    await TaskEx.Yield();

    if (count == 0)
        return;

    //is it possible to continue here with a clean call stack?
    DoLoop(count -1)
}

void Loop(int count)
{
    // This is a stub helper to make DoLoop appear synchronous. Even though
    // DoLoop is expressed recursively, no two frames of DoLoop will execute
    // their bodies simultaneously
    GeneralThreadAffineContext.Run(async () => { return DoLoop(count); });
}
...