我对这个话题不太熟悉,请原谅我,如果不是很清楚。
我创建了一个可移植的类库,它有一个ObservableCollection的Sections,每个secion都有一个ObservableCollection of Items。
这两个集合都绑定到单独的Win8和WP8应用程序的UI。
我正在尝试找出正确填充这些集合的正确方法,以便从PCL类更新UI。
如果该类在win8项目中,我知道我可以执行类似Dispatcher.BeginInvoke的操作,但这不会转换为PCL,也不能在WP8项目中重用它。
在这个帖子(Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync)中,我发现了SynchroniationContext类。
我传入了对主应用程序的SynchroniationContext的引用,当我填充这些部分时,我可以这样做,因为它只是一个对象正在更新:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
UpdateSections(sections);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(UpdateSections, sections);
}
然而,当我尝试用文章做同样的事情时,我必须引用部分和文章,但Post方法只允许我传入一个对象。
我试图使用lambda表达式:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
section.Items.Add(item);
}, null);
}
但我猜这不正确,因为我收到了关于“为不同线程编组”的错误。
那我在哪里错了?如何从PCL正确更新两个集合,以便两个应用程序也可以更新其UI?
非常感谢!答案 0 :(得分:2)
很难说没有看到其余的代码,但我怀疑是否与Portable Class Libraries有关。很高兴看到有关异常的详细信息(类型,消息和堆栈跟踪)。
使用多于参数调用Post()的方式看起来是正确的。如果您删除if检查并且只是总是通过SynchronizationContext.Post()
会发生什么?
BTW:我没有明确传入SynchronizationContext
。我假设在UI线程上创建了ViewModel。这允许我像这样捕获它:
public class MyViewModel
{
private SynchronizationContext _context = SynchronizationContext.Current;
}
答案 1 :(得分:1)
我建议至少在您的ViewModel中,所有公开可观察的状态更改(即属性更改通知和对ObservableCollections的修改)都发生在UI线程上。我建议对模型状态更改做同样的事情,但让它们在不同的线程上进行更改并将这些更改封送到ViewModel中的UI线程可能是有意义的。
要做到这一点,当然,您需要能够在可移植代码中切换到UI线程。如果SynchronizationContext不适合您,那么只需为调度程序创建自己的抽象(即IRunOnUIThread)。
答案 2 :(得分:0)
您获得“在不同线程上编组”错误的原因是您没有将项目作为Post(action,state)方法上的“状态”对象添加到列表中。
您的代码应如下所示:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
var item = (YourItemnType) e;
section.Items.Add(item);
}, item);
}
如果您进行了更改,您的代码将在PCL中正常运行。