我是否可以在Caliburn Micro中使用Coroutines帮助执行异步操作?

Ale*_*lex 0 c# asynchronous coroutine windows-phone-7 caliburn.micro

从文档中我意识到我可以使用Caliburn Micro的协同程序进行异步操作.开箱即用,没有额外的技术.所以我在Windows Phone应用程序中实现了下一个代码:

public class SimpleViewModel : Screen
{
    // ...

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

        Coroutine.BeginExecute(RunTask());
    }

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

SimpleTask:

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

    public event EventHandler<ResultCompletionEventArgs> Completed;
}
Run Code Online (Sandbox Code Playgroud)

我希望Execute方法中的代码将运行异步.但这不会发生.我的UI线程被阻止了10秒钟.

我犯了哪个错误?或者我对协同程序的异步性质的假设是错误的?

小智 12

我花了一整天时间搜索和尝试代码示例,最终得到了一些有效的东西(即使用不阻止UI的Caliburn Coroutines的异步操作),所以我允许自己分享它.

据我所知,Caliburn中的Coroutines不处理线程,它们只是提供了一种优雅的方法来在一个方法中处理异步执行和控制代码.必须使用其他工具(如BackgroundWorkers)来处理后台线程中的操作.

对于silverlight,我发现这个链接非常有趣.目的是将后台工作程序包含在一个包含协程调用的类中.

正如我在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 { };

    }
}
Run Code Online (Sandbox Code Playgroud)

在我的一个ViewModel中,以下内容:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

这样,当我单击ProcessTask按钮时,UI不会被冻结,并且计算结果会在后台工作进程可用时立即显示.IsBusy状态不是强制性的,但显示了UI相关状态如何进入面向异步的代码.

希望这会帮助我另一个人!