Продолжения с использованием Async CTP

Можно ли использовать 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)
}

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


person Roger Johansson    schedule 14.04.2011    source источник


Ответы (1)


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

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

Под сходством потоков мы подразумеваем, что асинхронные продолжения обрабатываются в том же контексте, что и исходный поток, аналогично поведению для 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); });
}
person Theo Yaung    schedule 14.04.2011
comment
Где находятся эти расширения? У меня установлено асинхронное обновление SP1. Не могу найти yield или generalthreadaffinecontext - person Roger Johansson; 15.04.2011
comment
GeneralThreadAffineContext не является частью официального API — на самом деле это некоторый вспомогательный код в образце модульного тестирования. Кроме того, для целей CTP Yield() — это метод вне TaskEx, потому что наша цель состояла в том, чтобы API-интерфейсы платформы CTP можно было развертывать без необходимости исправления платформы .NET. - person Theo Yaung; 16.04.2011