我花了一整天的时间寻找和尝试代码示例,最终得到了一些可行的东西(即使用不阻塞 UI 的 Caliburn Coroutines 的异步操作),所以我允许自己分享它。
据我了解,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 { };
}
}
在我的一个 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;
}
这样,当我单击 ProcessTask 按钮时,UI 不会冻结,并且计算结果会在后台工作进程可用时立即显示。IsBusy 状态不是强制性的,但显示了 UI 相关状态如何进入面向异步的代码。
希望这会帮助另一个我!