我如何从backgroundWorker线程创建通用控件?

时间:2010-08-17 08:32:33

标签: c# silverlight thread-safety backgroundworker new-operator

使用后台工作程序创建对象模型时遇到了麻烦。

据我了解原因,我无法找到解决方法。

这是伪逻辑:

  • 调用Webservice async

  • 收到后,打开后台工作人员,并将数据加载到后台的控件中

  • 在Load方法中,搜索现有对象,如果找不到,则创建一个新对象。

创建的所有对象都从Control继承(带有透明的抽象层)。

当我在主线程上创建控件时,该函数正常工作:

public static T Find<T>(ObservableCollection<T> collection, int objectId)
        where T : FormaliteBaseControl, new()
    {
        foreach (T item in collection)
        {
            if (item.ObjectId == objectId)
                return item;
        }

        return new T();
    }

当然,从后台线程调用时,“new T()”会发生交叉线程异常 在Silverlight中,无法同步调用Dispatcher.Invoke。

虽然我以这种方式创建了大约450个对象,但我希望在后台保留对象模型,而不会降低Thread.Sleep或其他“优秀”方法的性能。

感谢您的回答。

2 个答案:

答案 0 :(得分:0)

您是否正在创建实际的UI控件?这就是我所暗示的。如果是这种情况,将它委托给后台线程似乎没有意义。为什么?因为最终是UI对象,所以必须在UI线程上创建它们。我知道你担心阻塞,但你所有的主要工作最终都要被编组回UI。

可能最好的情况是提供一个pub / sub模型。您可以将具有逻辑的线程生成到后台线程,但它永远不会实例化对象。相反,它将发布请求。在UI线程上,您可以侦听并创建对象。 Reactive Extensions(Rx)对此特别有用,因为您可以将ObservableCollection转换为Observable,然后将迭代编组到UI。

答案 1 :(得分:0)

谢谢你们两位。

我的控件构建了一个树视图。 实际上,根对象包含4个扩展器,它们将一个itemscontrol作为子控件(包含45个对象)。每个子对象都有另一个带有itemscontrol的扩展器,有大约10个孩子。

@WPCoder:由于itemscontrol很少包含10个以上的对象,很少有45个,并且由于这些项目可以有多个高度和子项,Virtualization确实没有帮助我(是的,我已经尝试过了)

经过一些测试,我发现这是模板化的步骤。我的对象声明适合一秒钟。因此,当对象模型变得很大时,我使用了一种解决方法来保持第一个深层对象崩溃。 用户可以在启动时强制扩展作为参数,但是他们知道这种方法的倒退。

@Jeremy,我想MVVM是实施解决方案的最佳解决方案? 我会阅读Reactive Extensions。感谢。