WPF应用程序中多个线程之间的通信

时间:2010-05-30 01:12:07

标签: c# wpf c#-4.0

我为我的代码添加了一个事件处理程序,它破坏了对SystemHTA类中CollectionViewSources的所有访问,说“调用线程无法访问此对象,因为另一个线程拥有它”。我的班级在“this.systemHTA = new SystemHTA();”时正在工作被放置在DeviceManager_StateChanged()函数之外。

    public partial class MainWindow : Window
    {
        private DeviceManager DeviceManager = DeviceManager.Instance;
        public SystemHTA systemHTA;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DeviceManager.StateChanged += new EventHandler<DeviceManagerStateChangedEventArgs>(DeviceManager_StateChanged);
            DeviceManager.Initialize();
        }

        void DeviceManager_StateChanged(object sender, DeviceManagerStateChangedEventArgs e)
        {
            if (e.State == DeviceManagerState.Operational)
            {
                this.systemHTA = new SystemHTA();
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.systemHTA.GetViewSourceTest();
        }
    }


    public class SystemHTA
    {
        private CollectionViewSource _deviceTestSource;

        public SystemHTA()
        {
            _deviceTestSource = new CollectionViewSource();
            _deviceTestSource.Source = CreateLoadData<HWController>.ControllerCollection;
        }

        public void GetViewSourceTest()
        {
            ListCollectionView view = (ListCollectionView)_deviceTestSource.View; //This creates an error saying a thread already owns _deviceTestSource
        }
    }

4 个答案:

答案 0 :(得分:0)

您在这里寻找的是Dispatcher.BeginInvoke。看看这里有一个完整的解释:

Dispatcher.BeginInvoke

以下是一些更具体的帮助,可以帮助您前进:

Working with the WPF dispatcher

祝你好运。

答案 1 :(得分:0)

以下是一些使用Invoke解决问题的示例代码:cross thread operation not valid。您需要从创建线程访问信息。

答案 2 :(得分:0)

好的,CollectionViewSource派生类,BindableList,ObservableCollection等这些类只能在主调度程序线程中创建。

但是你必须尝试以下排序, 仅在WPF派生类中创建collectionviewsource,使用List&lt;&gt;用于在不同线程中加载对象的类,一旦完成,您可以从列表转移到collectionviewsource,如下所示,我建议使用BindingList,因为您可以添加多个项目来禁用刷新以消除闪烁。

在WPF类中隐式创建集合对象,如下所示

public class MyWindow : UserControl{
BindingList<MyObject> ObjectList = new BindingList<MyObject>;
    public MyWindow(){
        ObjectList.AllowAdd = true;
        ObjectList.AllowDelete = true;
        ObjectList.AllowEdit = true;
    }
    public void LoadObjects(){
       ThreadPool.QueryUserItem( (s)=>{
           // load your objects in list first in different thread
           List<MyObject> list = MyLongMethodToLoadObjects();
           Dispatcher.BeginInvoke( (Action)delegate(){
               list.RaiseEvents = false;
               foreach(MyObject obj in list){
                   ObjectList.Add(obj);
               }
               list.RaiseEvents = true;
               list.ResetBindings();
           });
       });
    }
}

我不知道这段代码格式不正确,但你可以尝试在visual studio中看到它以获得正确的想法。

答案 3 :(得分:0)

简单而稳定的解决方案是使用 BackgroundWorker 。 阅读这篇文章BackgroundWorker