2010-05-30 5 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

Ok, CollectionViewSource 파생 클래스, BindableList, ObservableCollection 등 이러한 클래스는 주 디스패처 스레드에서만 만들 수 있습니다.

당신의 WPF 파생 클래스에서만 collectionviewsource를 만들고 List <> 클래스를 사용하여 다른 스레드에서 객체를로드하면 완료되면 목록에서 collectionviewsource로 다음과 같이 전송할 수 있습니다 , 깜박임을 제거하기 위해 새로 고침을 비활성화하는 여러 항목을 추가 할 수 있으므로 BindingList를 권장합니다.

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(); 
      }); 
     }); 
    } 
} 

을 따를

는이 코드가 제대로 지정하지 않을 몰라요 당신의 WPF 클래스에서 암시 적 컬렉션 객체를 생성하지만 당신은 올바른 아이디어를 얻을 Visual Studio에서 그것을보고 시도 할 수 있습니다.

+0

ObservableCollection으로 CollectionViewSource를 교체하면 모든 것이 정상적으로 작동합니다. 나를 올바른 방향으로 가리켜 주셔서 감사합니다. – Robert

0

여기서는 Dispatcher.BeginInvoke를 찾고 있습니다. 자세한 설명은 여기를 보라 :

여기

Dispatcher.BeginInvoke

좀 더 구체적인 도움이됩니다 당신은뿐만 아니라 가야 :

Working with the WPF dispatcher

행운을 빕니다.

+0

마찬가지로 상황을 돕기 위해 데이터 바인딩을 조사하고 싶을 수 있습니다. 데이터 바인딩은 자동으로 Dispatcher를 거칩니다. – Agies

0

다음은 Invoke를 사용하여 문제를 해결할 수있는 몇 가지 샘플 코드입니다. cross thread operation not valid. 생성 스레드의 정보에 액세스해야합니다.

0

간단하고 안정적인 해결책은 BackgroundWorker입니다. 이 기사 읽기 BackgroundWorker

관련 문제