C# 我能否仅在Caliburn Micro中的协程帮助下异步执行操作?

C# 我能否仅在Caliburn Micro中的协程帮助下异步执行操作?,c#,windows-phone-7,asynchronous,caliburn.micro,coroutine,C#,Windows Phone 7,Asynchronous,Caliburn.micro,Coroutine,从文档中,我意识到我可以使用Caliburn Micro的协程进行异步操作。开箱即用,无需额外技术。因此,我在我的Windows Phone应用程序中实现了下一个代码: public class SimpleViewModel : Screen { // ... protected override void OnViewLoaded(object view) { base.OnViewLoaded(view); Coroutine.B

从文档中,我意识到我可以使用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();
    }

    // ...
}
公共类SimpleViewModel:屏幕
{
// ...
加载视图时受保护的覆盖无效(对象视图)
{
base.OnViewLoaded(视图);
Coroutine.BeginExecute(RunTask());
}
公共IEnumerator RunTask()
{
返回新的SimpleTask();
}
// ...
}
SimpleTask:

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

    public event EventHandler<ResultCompletionEventArgs> Completed;
}
公共类SimpleTask:IResult
{
public void Execute(ActionExecutionContext上下文)
{
睡眠(10000);
}
公共事件事件处理程序已完成;
}
我希望Execute方法中的代码将异步运行。但这不会发生。我的UI线程被阻塞了10秒


我哪里出错了?或者我对协同路由的异步性质的假设是错误的?

您的问题是,Coroutine.BeginExecute立即运行代码。您必须在单独的任务或线程中运行代码,或者在协同程序中调用异步代码。协同程序代码不会自动阻止UI阻塞

微协同程序帮助您在一个特定的环境中执行异步例程 同步方式。而不是相反。关于你的问题:出去 盒子的CM为您提供了找到解决方案的可能性 快…;-)

为了完成你想做的事情,我建议你看一看 在.NET BackgroundWorker上创建一个协作程序(IResult) 它


我花了一整天的时间搜索和尝试代码示例,以最终获得一些有用的东西(即使用Caliburn协程的异步操作,不会阻塞UI),因此我允许自己分享它

据我所知,Caliburn中的协程不处理线程,它们只是提供了一种优雅的方式,可以在一个方法中处理异步执行和控制代码。必须使用其他工具(如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 { };

    }
}
使用系统;
使用Caliburn.Micro;
使用系统组件模型;
名称空间MyApp.Implementation
{
公共类背景协同程序:IResult
{
私有只读系统。操作;
公共背景协同程序(System.Action)
{
这个动作=动作;
}
public void Execute(ActionExecutionContext上下文)
{
使用(var backgroundWorker=new backgroundWorker())
{
backgroundWorker.DoWork+=(e,发送方)=>action();
backgroundWorker.RunWorkerCompleted+=(e,发件人)=>Completed(这是新的ResultCompletionEventArgs());
backgroundWorker.RunWorkerAsync();
}
}
public event EventHandler Completed=委托{};
}
}
在我的一个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;
    }
public IEnumerable ProcessTask()
{
IsBusy=true;
TempObject结果=null;
for(int i=1;i<4;i++)//模拟处理多个项、文件、字段的循环。。。
{
收益回报新背景协同计划(()=>
{
System.Threading.Thread.Sleep(1000);//另一个线程中耗时的任务
结果=新的临时对象(“项目”+i);
});
MyObservableCollection.Add(result);//在GUI线程中用结果更新UI
}
IsBusy=false;
}
这样,当我单击ProcessTask按钮时,UI不会冻结,计算结果在后台工作进程可用时立即显示。IsBusy状态不是必需的,但显示了与UI相关的状态如何进入面向异步的代码


希望这对我有帮助

在某种程度上,这比C#5.0中的
async
wait
关键字更可取吗?@RobertHarvey我认为使用什么没有区别。文档和讨论论坛说,协同程序提供了与
async
wait
相同的功能。但是我想知道我是否正确地理解了文档?这是否意味着,如果他能够脱离UI线程,协同程序将工作得很好?或者你真的需要为每个协同程序创建一个线程吗?谢谢你的回答。但是,如果我在绑定到按钮的操作中放置一个协同程序,它是否会异步工作呢?@RobertHarvey我已经在Codeplex上的讨论论坛链接上发布了我自己的答案。检查一下。它非常有用。