2009-07-08 4 views
0

BackgroundWorker 내에서 필터링하려고하는 WPF ListView가 있습니다. 내 코드는 다음과 같습니다. "다른 스레드가 그것을 소유하고 있기 때문에 호출 스레드가이 개체에 액세스 할 수 없습니다"이 코드는 필터링을 통해 실행 WPF BackgroundWorker ListView 필터 문제

Dim Worker As New BackgroundWorker 
AddHandler Worker.DoWork, AddressOf Me.FilterAsync 
Me.TextBoxText = Me.TextBox.Text 
Worker.RunWorkerAsync(Me.TextBox) 

Private Sub FilterAsync(ByVal sender As Object, ByVal e As DoWorkEventArgs) 
    ' 
    Dim BackgroundWorker As BackgroundWorker = CType(sender, BackgroundWorker) 
    Dim Text As String = e.Argument.ToString 
    ' 
    Dim ListView As ListCollectionView = CType(CollectionViewSource.GetDefaultView(Me.ListView.ItemsSource), ListCollectionView) 
    If Text <> String.Empty Then 
     ListView.Filter = New Predicate(Of Object)(AddressOf Me.FindItemsAsync) 
    Else 
     ListView.Filter = Nothing 
    End If 
    ' 
End Sub 

그러나 그것이 오류와 함께 실패

ListView.Filter = New Predicate(Of Object)(AddressOf Me.FindItemsAsync) 

여기서 어떤 문제가 발생합니까? BackgroundWorker를 통해 필터링을 통해 샘플을 찾을 수없는 것 같습니다.

업데이트 : 누구나 BackgroundWorker를 사용하여 WPF ListView를 필터링하는 샘플을 알고 있습니까?

+0

좀 더 완벽한 샘플을 제공해 주시겠습니까? 제공된 스 니펫을 사용하면 오류를 재생산 할 수 없으며 다른 결과로 이어질만큼 너무 많이 추측하고 싶지 않습니다. – STW

+0

고마워요! 나는 더 완전한 샘플을 가능한 한 빨리 얻을 수 있도록 노력할 것이다.Stackoverflow가 질문에 많은 양의 코드를 덤핑하는 대신 파일 첨부를 수락하면 좋을 것입니다. WPF ListView를 필터링하기위한 BackgroundWorker가있는 샘플 코드가 있습니까? – Luke

+0

구체적으로 말하자면, 크로스 쓰레드 문제 일 수 있습니다. 그리고 더 완전한 샘플을 통해 문제를 해결하는 방법을 알려줄 수 있습니다. – STW

답변

1

필자는 필터를 실행하는 것이 오래 걸릴 것으로 생각합니다. 시간이 걸리므로 백그라운드 스레드에서 필터링 코드를 실행하려고합니다. 이는 단지 불가능합니다.

UI 스레드와 필터 (필터 안의 코드 및 필터 설정 포함)에 대한 코드는 UI 스레드에서 실행해야합니다.

BackgroundWorker 코드 내에서 필터링 할 항목 만 포함 된 새 목록을 만든 다음 BackgroundWorker가 끝나고 UI 스레드로 돌아온 후 새 목록을 설정하면됩니다 ListView의 ItemSource.

0

컨트롤에 바인딩 된 ListCollectionView은 해당 컨트롤을 만든 스레드에서만 액세스 할 수 있습니다. 토마스 코멘트에 지적한 것처럼 그래서 당신은 ... UI 스레드에서

+0

감사합니다. 좋아, UI 스레드에서 필터를 설정하도록 설정하면 UI 스레드뿐만 아니라 BackgroundWorker 스레드 내에서도 실행되지 않습니다. – Luke

+0

필터를 할당하면 각 항목에 대한 조건부 평가가 트리거되므로 예, UI 스레드에서 실행됩니다. 사실 나는 백그라운드 스레드에서 필터링을 수행 할 수 있는지 확신하지 못합니다. 적어도 쉽지는 않습니다. –

0

Filter 속성을 설정할 수 있습니다,이 방법은 전적으로 WPF 이층, 그것은 윈폼 건물 토마스의 대답에

접근입니다 백그라운드 스레드가 UI를 업데이트해야하는 경우 먼저 UI를 만든 스레드로 전환해야합니다.

단순화하기 위해 단일 "UI 스레드"와 "백그라운드 스레드"를 생각해 볼 수 있습니다. UI 쓰레드는 화면에 그림 그리기, 사용자 상호 작용 처리 등을 담당합니다 ... UI를 수정하는 백그라운드 스레드의 호출은 모든 종류의 엉망을 일으킬 수 있습니다. 따라서 .NET 2.0 (또는 어쩌면 1.1)에서 기본값 행동은 잠재적으로 위험한 호출이 성공하는 것을 허용하기보다는 예외를 throw하는 것입니다.

일반적으로 (최소한 2.0 세계에서) 업데이트 할 폼/컨트롤을 "호출"하면됩니다 ("2.0"세계에서). "호출"은 프레임 워크에서 약간 모호하지만 UI 컨텍스트에서 제어합니다 "UI 스레드로 돌아 가기"를 의미합니다.

Private DelegateSub UpdateSomeUICaller() 
Private Sub UpdateSomeUI() 
    If Me.InvokeRequired Then 
     Dim delg as new UpdateSomeUICaller(AddressOf UpdateSomeUI) 
     Me.Invoke(delg) 
     Exit Sub 
    End If 

    Me.SomeUiControl.Text = "Hello from the UI Thread!" 

End Sub 

ONE BIG WARNING :

는 2.0 전형적인 패턴이 라인을 따라 것 수행하기 위해 사용되는이 예에서는 개체는 인 "호출"부재를 포함한다 "delg" NOT 당신이 찾고있는 Invoke 메서드는 "delg.Invoke()"가 아닌 "Invog (delg)"가 필요합니다 - 제가 언급 한 모호성입니다

+1

Me.Invoke 및 Me.InvokeRequired는 WPF가 아닌 Windows Forms 용입니다. WPF에서는 Dispatcher 속성을 사용하여 UI 스레드에서 메서드를 호출합니다. –

+0

@Thomas는 알기에 진지하게 알고 있습니다. WPF에 대한 문의가 거의 필요 없다고 말할 수 없다면 (실제로 XAML을 시작한 것처럼 보입니다) ... – STW