【发布时间】:2015-10-06 07:30:03
【问题描述】:
场景(WPF 桌面应用,.NET 4.6):
我有一个显示一些“任务”的列表框。 目标是启动一个异步进程,该进程将遍历所有任务,执行每个任务。
这是一个长时间运行的过程,因此所需的行为是禁用大多数命令而不锁定 UI,以便用户仍然可以取消它。 它应该标记每个任务(待机、运行、完成),以便 UI 可以动态更新,为最终用户提供反馈(使用基于“状态”枚举的样式)。
问题
当命令 (ExecuteTasks) 执行时,我收到消息:
这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。
我的问题是:如何使用 ReactiveUI 解决这个问题?我相信答案在调度程序的某个地方,但到目前为止我还想不通。
代码如下:
public ReactiveCommand<object> AddTask { get; }
public ReactiveCommand<object> ExecuteTasks { get; }
public IPlugin SelectedTask
{
get { return selectedTask; }
set { this.RaiseAndSetIfChanged(ref selectedTask, value); }
}
public ReactiveList<IPlugin> Tasks
{
get { return tasks; }
}
public ReactiveList<PluginFactoryGroup> TaskFactories
{
get
{
return taskFactories;
}
}
public AppViewModel(IExecutionContext context, IEnumerable<PluginFactoryGroup> taskFactories)
{
this.context = context;
// initialize lists
tasks = new ReactiveList<IPlugin>() { ChangeTrackingEnabled = true };
this.taskFactories = new ReactiveList<PluginFactoryGroup>(taskFactories);
// create observables to determine whether or not commands can be executed
var canEdit = /*...*/
var canExecute = /*...*/
// initialize commands
AddTask = ReactiveCommand.Create(canEdit);
AddTask.Subscribe(_ => {
if (SelectedFactory != null)
{
var t = SelectedFactory.Create(this.context);
Tasks.Add(t);
SelectedTask = t;
}
});
ExecuteTasks = ReactiveCommand.CreateAsyncTask(canExecute, _ =>
{
return Task.Run(() =>
{
object result = null;
foreach (var item in Tasks)
{
item.Clear();
item.Validate();
}
if (Tasks.Any(e => e.Status == TaskStatus.Error))
{
Tasks.Reset();
return result;
}
foreach (var item in Tasks)
{
item.Status = XrmTools.Plugins.TaskStatus.Running;
item.Execute();
item.Status = XrmTools.Plugins.TaskStatus.Completed;
}
return result;
});
});
}
【问题讨论】:
标签: c# wpf reactive-programming reactiveui