Какая будет лучшая альтернатива для ключевого слова await в .NET 4.0? У меня есть метод, который должен возвращать значение после асинхронной операции. Я заметил, что метод wait() полностью блокирует поток, что делает асинхронную операцию бесполезной. Каковы мои возможности для запуска операции async при освобождении потока пользовательского интерфейса?
Ожидать альтернативы в .NET 4.0?
Ответ 1
Я думаю, что ваши основные параметры
- Использование
Task
и.ContinueWith()
- Использование Async CTP и
async
/await
- Использование Реактивные расширения
Самый простой способ - установить 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
}