2010-05-30 89 views
0

我向我的代码添加了一个事件处理程序,并且它打破了SystemHTA类中CollectionViewSources的所有访问,说“调用线程不能访问此对象,因为不同的线程拥有它”。当我的课程“this.systemHTA = new SystemHTA();”被放置在DeviceManager_StateChanged()函数的外部。WPF应用程序中多个线程之间的通信

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 
     } 
    } 

回答

0

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

但是你一定要试试以下类似的东西, 只在您的WPF派生类创建collectionviewsource,使用列表<>类加载在不同的线程的对象,一旦完成后,你可以从列表传输到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中得到正确的想法。

+0

我结束了刚刚用ObservableCollection替换CollectionViewSource,一切正常。感谢您指点我正确的方向。 – Robert 2010-05-31 02:19:21

0

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

Dispatcher.BeginInvoke

下面是一些更具体的帮助,让你去还有:

Working with the WPF dispatcher

好运。

+0

就像旁边你可能想看看数据绑定,以帮助情况。数据绑定自动通过分派器。 – Agies 2010-05-30 01:48:02

0

简单稳定的解决方案是使用BackgroundWorker。 阅读本文BackgroundWorker