Como lidar com o ObservableCollection <> Resultado de uma tarefa paralela no MVVM?
-
26-09-2019 - |
Pergunta
Estou coletando dados em uma tarefa separada e quero vincular dados o resultado a um componente GUI usando um ObservableCollection<>
. Então, meu código vai algo assim:
private ObservableCollection<MyItem> _items;
public ObservableCollection<MyItem> Items
{
get { return _items; }
set
{
if (_items.Equals(value))
{
return;
}
_items = value;
RaisePropertyChanged("Items");
}
}
private void LoadData()
{
Task task = Task.Factory.StartNew(() =>
{
ObservableCollection<MyItem> itms = _htmlParser.FetchData(...);
Dispatcher.CurrentDispatcher.Invoke((Action)delegate
{
Items = itms;
});
});
}
Os dados são obtidos a partir de um componente fazendo algumas solicitações HTTP. O erro que estou recebendo é:
Must create DependencySource on same Thread as the DependencyObject.
Estou usando a estrutura MVVM Light Toolkit. Também tentei enviar o resultado como uma mensagem, mas isso acabou na mesma mensagem de erro. Alguma ideia ou indicador?
EDIT: Aqui está a questão:
public class MyItem
{
public string Id { get; set; }
public string Name { get; set; }
public BitmapImage Image { get; set; } // <--- A big No No because it inherits from the DependencyObject
public Uri Uri { get; set; }
}
Eu mudei o BitmapImage
para um byte[]
tipo de dados.
Solução
A exceção que você está recebendo ("deve criar dependencySource no mesmo thread que o dependencyObject") indica que algo está sendo criado em um encadeamento de segundo plano e usado no encadeamento da interface do usuário. Existem controles de interface do usuário que estão sendo criados e armazenados na coleção para uso pela interface do usuário?
Vejo que a própria ObservableCollection está sendo criada em um tópico de segundo plano, mas não acho que esse seja o problema - infelizmente não estou no escritório para codificar e confirmar isso.
Outras dicas
Você pode tentar substituir o Dispatcher.CurrentDispatcher
em Application.Current.Dispatcher
Não tenho certeza sobre isso embora