2009-07-25 3 views
2

InitializeComponents 이후 내 윈도우 생성자에서 객체를 만들고이를 DataGrid에 바인딩해야합니다. 개체 생성에 너무 많은 시간이 걸리므로 창을 표시하는 데 시간이 걸립니다. 그래서 객체 생성을 백그라운드 스레드로 옮기고 바인딩을 수행하기 위해 dispatcher.invoke를 수행하여 UI 스레드로 "위임"하기로 결정했습니다. 그러나 이것은 실패합니다.WPF : UI 스레드와 백그라운드 스레드간에 객체 전달

이상한 일은 Dispatcher.invoke 내부에있는 사각형의 가시성을 설정하려고하면 작동하지만 DataGrid.setbinding은 작동하지 않습니다. 어떤 아이디어? 백그라운드 작업자와 threadstart를 사용하여 동일한 작업을 시도했지만 동일한 오류가 계속 발생합니다. Dispatcher 내부에서 일어나는 일이 대리자를 호출하더라도 DataGrid 개체에 액세스 할 수 없습니다. 이것이 어떻게 작동하는지에 대한 이해에서 뭔가를 놓치고있는 것은 확실합니다. 어떤 제안이라도 대단히 감사하겠습니다. 감사!

StartupDelegate s = new StartupDelegate(CreateModel); 
s.BeginInvoke(delegate(IAsyncResult aysncResult) { s.EndInvoke(aysncResult); }, null); 

internal CreateModel() 
{ 
    Model d = new Model(); 
    Dispatcher.Invoke(DispatcherPriority.Normal, 
         new Action<Model>(
          delegate(Model d1) 
          { 
           mModel = d1; // mModel is a property defined in Window 
           Binding b = new Binding(); 
           b.Source = mModel; 
           MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); // << dies here with - The calling thread cannot access this object because a different thread owns it. 
          }    
} 

UPDATE : 은 번을 실행 것 dispatchertimer를 사용하여 종료. 틱 대리인에 바인딩 코드를 넣는 것이 효과적입니다. 하지만 위의 코드가 왜 그렇게 궁금한 지 궁금합니다.

답변

0

나는 다른 방법을 제안합니다.

바인딩은 코드에서 호출하면 안되며 대신 XAML에서 정의해야합니다.

Model에 DependencyProperty를 하나 더 추가하고 "CurrentModel"이라고하고 초기 값을 NULL로 설정할 수 있습니다. 당신은 이미 mModel이라는 속성을 가지고있는 것처럼 보입니다, DependencyProperty입니까?

CurrentModel을 DataGrid에 바인딩하거나 XAML에서 컨트롤을 정의 할 수 있습니다.

대리인이 끝나면 Dispatcher.Invoke는 CurrentModel 만 설정해야하며 바인딩은 자동으로 수행됩니다.

+0

xaml에서이 작업을 시도한 것이 아니라 속성에 대한 바인딩을 설정하고 inited 속성을 null로 설정했습니다. 따라서 대표단은 mModel = d1이라는 한 줄만 있습니다.그러나 아무 일도 일어나지 않았습니다. 의존성 속성이 아니라 notifypropertychanged를 구현하는 일반 속성입니다. – Sharun

+0

개체가 DependencyObject에서 파생 된 경우 (창이있는 경우) INotifyPropertyChanged가 작동하지 않기 때문에 비슷한 문제가 있어도 DependencyProperty로 변경 한 이유는 의심 스럽습니다. –

0

어떤 디스패처 인스턴스에서 Invoke을 호출합니까?

나는 UI 스레드의 스레드가 아니라 CreateModel을 실행중인 백그라운드 스레드의 Dispatcher를 추측하고 있습니다.

DataGrid는 컨트롤이므로 DispatcherObject에서 파생됩니다. 이러한 각 객체는 소유자 스레드의 디스패처를 Dispatcher 속성을 통해 노출합니다.이 속성은 컨트롤의 메서드를 호출하는 데 사용해야합니다.

작동해야 호출에 디스패처를 변경 :

internal CreateModel() 
{ 
    Model d = new Model(); 

    // Invoke the action on the dispatcher of the DataGrid 
    MainDataGrid.Dispatcher.Invoke(DispatcherPriority.Normal, 
         new Action<Model>(
          delegate(Model d1) 
          { 
           mModel = d1; // mModel is a property defined in Window 
           Binding b = new Binding(); 
           b.Source = mModel; 
           MainDataGrid.SetBinding(TreeView.ItemsSourceProperty, mainb); 
          }    
} 

또한 배경 작업을 실행하기 전에 필드의 UI 스레드의 Dispatcher를 저장할 수 있지만 사용하여 더 나은 컨트롤의 Dispatcher는 의도를 보여줍니다 "이 컨트롤이 속한 스레드에 관계없이이 코드를 호출하려고합니다."

업데이트 : 방금이 컨트롤이 인스턴스 메서드라는 것을 알았습니다. 따라서 사용중인 Dispatcher 인스턴스가 올바른 것입니다. 늦은 밤 응답에 많은 도움이됩니다. 또한 코드가 IEnumerable로 모델을 대체하여 나를 위해 작동합니다. 모델에 특별한 것이 있습니까?

관련 문제