2012-08-16 2 views
0

Из документации я понял, что могу использовать сопрограммы Caliburn Micro для асинхронных операций. Из коробки и без дополнительных технологий. Так я реализовал следующий код в моем телефоне приложение с Windows:Могу ли я выполнять операции async только с помощью Coroutines в Caliburn Micro?

public class SimpleViewModel : Screen 
{ 
    // ... 

    protected override void OnViewLoaded(object view) 
    { 
     base.OnViewLoaded(view); 

     Coroutine.BeginExecute(RunTask()); 
    } 

    public IEnumerator<IResult> RunTask() 
    { 
     yield return new SimpleTask(); 
    } 

    // ... 
} 

SimpleTask:

public class SimpleTask : IResult 
{ 
    public void Execute(ActionExecutionContext context) 
    { 
     Thread.Sleep(10000); 
    } 

    public event EventHandler<ResultCompletionEventArgs> Completed; 
} 

Я надеялся, что код в Execute метод будет работать асинхр. Но этого не происходит. Моя UI-thread была заблокирована на 10 секунд.

Где я совершил ошибку? Или мое предположение о асинхронном характере сопрограмм было неправильным?

+0

Является ли это предпочтительным каким-либо образом для ключевых слов 'async' и' await' в C# 5.0? –

+0

@RobertHarvey Я думаю, что нет никакой разницы в том, что использовать. В документации и дискуссионном форуме говорится, что сопрограммы обеспечивают ту же функциональность, что и 'async' и' await'. Но я хочу знать, правильно ли я понимаю документацию или нет? – Alex

ответ

12

Я провел целый день в поисках и пытается образцы кода, чтобы, наконец, то, что работает (то есть асинхронные операции с использованием Caliburn Сопрограммы, которые не блокируют пользовательский интерфейс), поэтому я позволю себе поделиться ,

Насколько я понимаю, Coroutines в Caliburn не обрабатывает потоки, они просто обеспечивают элегантный способ выполнения асинхронного выполнения и управления кодом, обрабатываемым одним способом. Для обработки операций в фоновом потоке нужно использовать другие инструменты, такие как BackgroundWorkers.

Я нашел this link довольно интересно, для silverlight. Цель состояла в том, чтобы включить фонового работника в класс, который обертывает вызовы coroutine.

Как я хотел в WPF с небольшими различиями, я закончил с этим пример кода, который работает на моей машине:

Обертывание класса:

using System; 
using Caliburn.Micro; 
using System.ComponentModel; 

namespace MyApp.Implementation 
{ 
    public class BackgroundCoRoutine : IResult 
    { 
     private readonly System.Action action; 

     public BackgroundCoRoutine(System.Action action) 
     { 
      this.action = action; 
     } 

     public void Execute(ActionExecutionContext context) 
     { 
      using (var backgroundWorker = new BackgroundWorker()) 
      { 
       backgroundWorker.DoWork += (e, sender) => action(); 
       backgroundWorker.RunWorkerCompleted += (e, sender) => Completed(this, new ResultCompletionEventArgs()); 
       backgroundWorker.RunWorkerAsync(); 
      } 
     } 

     public event EventHandler<ResultCompletionEventArgs> Completed = delegate { }; 

    } 
} 

И в одном из моих ViewModels, следующее :

public IEnumerable<IResult> ProcessTask() 
    { 
     IsBusy = true; 
     TempObject result = null; 

     for (int i = 1; i < 4; i++) // Simulates a loop that processes multiple items, files, fields... 
     { 
      yield return new BackgroundCoRoutine(() => 
      { 
       System.Threading.Thread.Sleep(1000); // Time consuming task in another thread 
       result = new TempObject("Item " + i); 
      }); 

      MyObservableCollection.Add(result); // Update the UI with the result, in the GUI thread 
     } 

     IsBusy = false; 
    } 

при этом, когда я нажимаю на кнопку ProcessTask, интерфейс не замерзает, а вычисленные результаты появляются, как только они становятся доступными на фоне Wo rker процесс. Состояние IsBusy не является обязательным, но показывает, как состояния, связанные с пользовательским интерфейсом, могут перейти в асинхронный код.

Надеюсь, это поможет другому мне!

2

Ваша проблема заключается в том, что Coroutine.BeginExecute запускает коды немедленно. Вы должны либо запустить код отдельной задачей или потоком, либо вызвать асинхронный код внутри своей сопрограммы. В коде Coroutine нет ничего автоматического, который остановит ваш пользовательский интерфейс от блокировки.

+0

Означает ли это, что, если он может выйти из потока пользовательского интерфейса, сопрограммы будут работать нормально? Или вам действительно нужно создать поток для каждой сопрограммы? –

+0

Спасибо за ответ. Но будет ли он работать async, если я поместил сопрограмму в действие, которое привязано к кнопке, например? – Alex

+0

@RobertHarvey Я отправил свой собственный ответ со ссылкой на форум обсуждений на Codeplex. Проверь это. Это очень полезно. – Alex

1

Caliburn.Micro Coroutines поможет вам выполнить асинхронные процедуры в синхронном режиме . А не наоборот. Что касается вашей проблемы: Из из коробки КМ дает возможность найти решение довольно быстро ... ;-)

Чтобы сделать то, что вы хотели бы сделать, я бы порекомендовал вам взглянуть на .NET BackgroundWorker и создайте сопрограмму (IResult) около .

http://caliburnmicro.codeplex.com/discussions/391929

Смежные вопросы