Ожидать альтернативы в .NET 4.0?

Какая будет лучшая альтернатива для ключевого слова await в .NET 4.0? У меня есть метод, который должен возвращать значение после асинхронной операции. Я заметил, что метод wait() полностью блокирует поток, что делает асинхронную операцию бесполезной. Каковы мои возможности для запуска операции async при освобождении потока пользовательского интерфейса?

Ответ 1

Я думаю, что ваши основные параметры

Самый простой способ - установить Async CTP. Насколько мне известно, лицензия позволяет использовать коммерческое использование. Он исправляет компилятор и поставляется с DLL объемом 150 КБ, которые вы можете включить в свой проект.

Вы можете использовать Task и .ContinueWith(). Но это означает, что вам нужно предпринять некоторые усилия с обработкой exeption и контролем потока.

Задачи - это функциональная конструкция. Поэтому ContinueWith() не очень хорошо сочетается с императивными конструкциями, такими как циклы for или try-catch. Поэтому введены async и await, поэтому компилятор может помочь нам.

Если у вас нет такой поддержки компилятора (например, вы используете .Net 4.0), лучше всего использовать TAP вместе с функциональной структурой. Reactive Extensions - очень хорошая структура для обработки асинхронных методов.

Просто зайдите в Google для "реактивных задач расширения", чтобы начать.

Ответ 2

Вы можете реализовать поведение типа await с сопрограммами yield, я использую это в коде, отличном от 4.5. Вам нужен класс YieldInstruction, который извлекается из метода, который должен запускаться async:

public abstract class YieldInstruction
{
    public abstract Boolean IsFinished();
}

Затем вам понадобятся некоторые реализации YieldInstruction (a.e. TaskCoroutine, который обрабатывает задачу) и используют его таким образом (псевдокод):

public IEnumerator<YieldInstruction> DoAsync()
{
    HttpClient client = ....;
    String result;
    yield return new TaskCoroutine(() => { result = client.DownloadAsync(); });
    // Process result here
}

Теперь вам нужен планировщик, который обрабатывает выполнение инструкций.

for (Coroutine item in coroutines)  
{  
    if (item.CurrentInstruction.IsFinished())  
    {
         // Move to the next instruction and check if coroutine has been finished 
         if (item.MoveNext()) Remove(item);
    }
}

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

public IEnumerator<YieldInstruction> DoAsync()
{
    HttpClient client = ....;
    client.DownloadAsync(..);

    String result;
    while (client.IsDownloading)
    {
        // Update the progress bar
        progressBar.Value = client.Progress;
        // Wait one update
        yield return YieldInstruction.WaitOneUpdate;
    }
    // Process result here
}