2010-06-05 5 views
8

다중 스레드 WPF 응용 프로그램에서 ObservableCollection을 WPF 창 스레드가 아닌 스레드에서 업데이트하는 경우는 not possible입니다.ObservableCollection을 다른 스레드에서 업데이트 할 수없는 이유는 무엇입니까?

나는 there are workarounds을 알고, 그래서 제 질문은 예외은 "디스패처 스레드 다른 스레드에서의 SourceCollection 변경을 지원하지 않습니다 CollectionView의 이 유형을"피할 수없는 방법이다.

제 질문은 입니다. 왜 그런 예외가 있습니까? 어떤 스레드에서 컬렉션 업데이트를 허용 할 수없는 이유는 무엇입니까?

개인적으로 ObservableCollection이 다른 스레드에서 변경되면 UI 업데이트를 차단할 이유가 개인적으로 표시되지 않습니다. 두 개의 스레드 (병렬 객체 포함)가 동일한 객체에 액세스하는 경우 하나는 이벤트를 통해 객체 등록 정보의 변경을 수신하고 나머지 하나는 변경을 수행하며 적어도 잠금이 올바르게 사용되면 항상 작동합니다. 그렇다면 이유는 무엇입니까?

+0

.NET 4.5에는 'ObservableCollection'에서 스레드 간 작업을 돕는 기능이 추가되었습니다. [작업자 스레드를 통해 ObservableCollection을 업데이트하는 방법은 무엇입니까?] (http://stackoverflow.com/q/2091988/50079) – Jon

+0

모든 스레드에서 작동하며 바인딩 될 수있는 스레드 안전 솔루션을 제공하는 다음 링크를 사용해보십시오 여러 UI 스레드를 통해 : http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony

답변

15

첫 번째 ... 나는 당신의 고통을 느낍니다. UI 스레드 제한은 ... 통증이있을 수 있습니다

왜 에서이 이 만들어진 아닌 다른 스레드를 UI를 요소를 업데이트 할 수 없습니다?

제 질문은 왜 그런 예외가 무엇입니까?

간단히 말해서, 역사. Windows는 잠시 동안이고 Gui 작업의 일부분은 COM 등의 기술에 포함되어 있습니다 .... 그래서 그것을 변경하는 것은 사소한 것이 아닙니다 ... 무언가를 깨기가 아주 쉬울 것입니다. 다른 많은 문제가 있습니다. 그러나 나보다 똑똑한 누군가가 설명해야합니다. 나는 WPF 팀이 정말로이 제한을 없애고 싶다고 생각하고 그들은 꽤 열심히 일했다 ... 결국 핵심 OS 변경 요구의 수가 필요 없다고 생각한다. 그래서 그들은 계속 움직였다 .... 쥐.

컬렉션 업데이트를 모든 스레드에서 허용 할 수없는 이유는 무엇입니까?

가능성이 있습니다 ... 스레드로부터 안전함을 유지하려면 성능이 저하되고 복잡성이 증가합니다. 대부분의 경우 응용 프로그램은 다중 스레드 액세스를 요구하지 않습니다. 대부분의 경우 Microsoft가 수행하는 규칙과 동일한 제한 사항을 적용한다는 점을 이해하는 것이 중요합니다. 그들이 ObservableCollection을 thread-safe하게 만들었다면 우리는 ... locks, monitor 등등 같은 툴을 사용했을 것입니다. Ui thread 규칙을 깨뜨릴 수는 없습니다 ... 마술은 할 수 없습니다 ... 같은 규칙.내 질문이 예외 "CollectionView이 유형은 발송자 스레드에서 다른 스레드 로부터 SourceCollection을하지 지원 변경을한다"피하는 방법되지 않도록 내가 아는

는 해결 방법이 있습니다.

해결 방법은 없습니다 ... 해결 방법은 없습니다. ObservableCollection이 깨졌습니다. 그냥 스레드로부터 안전하지 않습니다. 스레드로부터 안전하게 만들거나 액세스 할 수 있어야합니다. 이것은 thread-safe가 아닌 모든 것에 대해 동일합니다 ... thread-safe가 필요한 경우 그렇게 만듭니다. 당신이 쓰레드를 사용하고 있다면 자물쇠와 같은 것을 알고 있습니다. 쓰레드를 사용하면됩니다. 잠금 장치가 제대로 을 사용하는 적어도 경우

은 ... ObservableCollection에이 다른 스레드에서 변경된 블록 UI 업데이트는 .... 항상

하면 ..., 를 작동합니다 자물쇠가 제대로 사용됩니다 ... 맞습니다! 다시 말하지만 Microsoft는 이러한 잠금 장치를 넣을 수는 있지만 매우 좋았습니다. 당신은 자물쇠를 넣을 수 있습니다. 또는 당신은 스레드 안전 접근 .... 많은 옵션을 줄 다른 전술을 사용합니다.

.net4.0의 Task Parallel Library은 이러한 문제를 해결하기위한 몇 가지 새로운 도구를 제공합니다.

// get the Ui thread context 
    _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

    Action DoInBackground = new Action(() => 
    { 
    /*...In the background... 
     ...process some data for an ObservableCollection...*/ 
    }); 

    Action DoOnUiThread = new Action(() => 
    { 
    /*...On the UI thread... 
     ...read/write data to an ObservableCollection...*/ 
    }); 

    // start the background task 
    var t1 = Task.Factory.StartNew(() => DoInBackground()); 
    // when t1 is done run t1..on the Ui thread. 
    var t2 = t1.ContinueWith(t => DoOnUiThread(), _uiScheduler); 
이 .... 그것은 단지

를 해결하려면 뭔가 같은 UI 요소의 스레드 선호도 요구 사항에 대해 생각하지 마십시오 입니다 ... 작업에 대한 컨텍스트를 설정할 수 있다는하거나 스레드가 특히 유용하다 그것은 작동합니다.

C# 및 .Net에는 스레딩을 악몽으로 처리하는 데 사용할 수있는 많은 도구가 있습니다. 그들을 사용하십시오. 그들은 재미있을 수 있습니다.

나는 담배를 피울거야.

10

컬렉션은 사용자 인터페이스 요소에 바인딩 된 경우 해당 사용자 인터페이스 요소는 컬렉션의 CollectionChanged 이벤트를 듣고, 당신은 컬렉션을 업데이트되는이 이벤트는 스레드에서 발생합니다.

그래서 문제는 사용자 인터페이스 요소입니다. 사용자 인터페이스 요소는 컬렉션 자체가 아닌 스레드가 생성 한 스레드에서만 액세스 할 수 있습니다.

관련 문제