2010-06-05 6 views
8

В многопоточном приложении WPF оно равно not possible для обновления ObservableCollection из потока, отличного от потока окон WPF.Почему невозможно обновить ObservableCollection из другого потока?

Я знаю there are workarounds, поэтому мой вопрос заключается не в том, чтобы избежать «Этого типа CollectionView не поддерживают изменения в его SourceCollection из потока, отличного от диспетчера потоков» исключения.

Мой вопрос: Почему такое исключение? Почему не удалось разрешить обновления коллекции из любого потока?

Лично я не вижу причины блокировать обновление пользовательского интерфейса, когда ObservableCollection изменен с других сторон. Если два потока (в том числе параллельные) обращаются к одному и тому же объекту, один из которых прослушивает изменения свойств объекта через события, а другой делает изменения, он всегда будет работать, по крайней мере, если блокировки используются должным образом. Итак, каковы причины?

+0

.NET 4.5 добавляет функции, помогающие с кросс-потоковыми операциями над 'ObservableCollection'; см. [Как обновить ObservableCollection с помощью рабочего потока?] (http://stackoverflow.com/q/2091988/50079) – Jon

+0

Попробуйте следующую ссылку, которая обеспечивает поточно-безопасное решение, которое работает из любого потока и может быть связано через несколько потоков пользовательского интерфейса: http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony

ответ

15

Первый ... Я чувствую вашу боль. Ограничение нити Ui может быть болью ...

Почему вы не можете обновить Ui элемента из нити, кроме того, он был созданными на?

Мой вопрос: почему существует такое исключение ?

Хорошо, в двух словах, история. Окна были примерно в то же время, и некоторые части работы Gui встроены в такие технологии, как COM и т. Д., Поэтому изменение его не является тривиальным ... было бы очень легко сломать что-то. Есть много других вопросов, которые я уверен ... но кто-то умнее меня должен будет объяснить их. Я считаю, что команда WPF действительно хотела снять это ограничение, и они работали над этим довольно сложно ... в конце концов, я думаю, что количество изменений ОС в ОС было неработоспособным ... поэтому они перешли на ... крысы.

Почему не удалось разрешить обновление обновлений из любой темы?

Было и возможно ... Изготовление чего-то потокобезопасного всегда стоит некоторых в производительности и усложняет работу. В большинстве случаев приложение не требует многопоточного доступа. Важно понимать, что, по большей части, Microsoft играет по тем же правилам, что и мы, и тем же ограничениям. Если бы они сделали ObservableCollection потокобезопасными ... они использовали бы те же инструменты, которые у нас есть ... блокировки, мониторы и т. Д. Они не могут сломать правило нити Ui больше, чем мы можем ... нет волшебства ... те же правила.

Я знаю, что есть обходные пути, так что мой вопрос заключается не в том, чтобы избежать «Это типа CollectionView не поддержки изменения в его SourceCollection из нити отличной от Dispatcher нити» исключения.

Нет обходных путей ... Не обходиться без проблем. ObservableCollection сломан. Это просто не потокобезопасно. Вы должны сделать это или получить доступ к нему, потокобезопасным. Это то же самое для всего, что не является потокобезопасным ... если вам нужно, чтобы он был потокобезопасным, тогда сделайте так. Если вы используете потоки, то знаете о замках и т. Д. ... используйте их ... для чего они предназначены.

... обновление блока UI, когда ObservableCollection изменяется от других потоков .... он всегда будет работать, по крайней мере, если замки используются правильно ....

Если замки используются правильно ... Точно! Опять же, Microsoft могла бы поместить эти блокировки, но они не сделали и по очень веским причинам. Вы можете вставить блокировки. Или вы используете другую тактику, которая даст вам потокобезопасный доступ ... множество опций.

В Task Parallel Library в .net4.0 представлены некоторые новые инструменты для решения этих проблем. Будучи в состоянии установить контекст для выполнения задачи или поток особенно полезен ...

// 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); 

Не думайте о требованиях к потоку УИ элементов, как-то работать вокруг .... это просто как это работает.

В C# и .Net есть много инструментов, которые вы можете использовать, чтобы нарезать немного меньше кошмара. Используйте их ... они могут быть забавными.

Я собираюсь курить.

10

Если ваша коллекция привязана к элементам пользовательского интерфейса, эти элементы пользовательского интерфейса прослушивают событие коллекции CollectionChanged, и это событие возникает в потоке, на котором вы обновляете коллекцию.

Таким образом, проблема связана с элементами пользовательского интерфейса, доступ к которым возможен только из потока, на котором они были созданы, а не с самой коллекцией.

Смежные вопросы