1

我对这个话题不是很有经验,所以如果这不是很清楚,请原谅我。

我创建了一个可移植的类库,它有一个 ObservableCollection 部分,每个部分都有一个 ObservableCollection 项目。

这两个集合都绑定到单独的 Win8 和 WP8 应用程序的 UI。

我试图找出正确填充这些集合的正确方法,以便从 PCL 类更新 UI。

如果该类在 win8 项目中,我知道我可以执行类似 Dispatcher.BeginInvoke 的操作,但这不会转化为 PCL,我也无法在 WP8 项目中重用它。

在这个线程(可移植类库等效于 Dispatcher.Invoke 或 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?

非常感谢!

4

3 回答 3

2

很难说没有看到其余的代码,但我怀疑这与可移植类库有什么关系。最好查看有关异常的详细信息(类型、消息和堆栈跟踪)。

您使用多个参数调用 Post() 的方式看起来是正确的。如果您删除 if 检查并始终通过会发生SynchronizationContext.Post()什么?

顺便说一句:我没有明确传递SynchronizationContext. 我假设 ViewModel 是在 UI 线程上创建的。这使我可以像这样捕获它:

public class MyViewModel
{
    private SynchronizationContext _context = SynchronizationContext.Current;
}
于 2013-04-28T19:07:09.770 回答
1

我建议至少在您的 ViewModel 中,所有可公开观察的状态更改(即属性更改通知和对 ObservableCollections 的修改)都发生在 UI 线程上。我建议对你的模型状态更改做同样的事情,但让它们在不同的线程上进行更改并将这些更改编组到你的 ViewModel 中的 UI 线程可能是有意义的。

当然,要做到这一点,您需要能够在可移植代码中切换到 UI 线程。如果 SynchronizationContext 不适合您,那么只需为调度程序创建您自己的抽象(即 IRunOnUIThread)。

于 2013-04-30T19:07:02.273 回答
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 中正常工作。

于 2014-02-03T19:11:41.133 回答