What's the best way to update an ObservableCollection from another thread?

后端 未结 5 945
终归单人心
终归单人心 2020-12-23 17:06

I am using the BackgroundWorker to update an ObservableCollection but it gives this error:

\"This type of CollectionVi

相关标签:
5条回答
  • 2020-12-23 17:40

    If you initialize the collection in the constructor it will be on the default Application thread.

    To invoke the main thread you can do this:

    Application.Current.Dispatcher.Invoke((Action)(() =>
        {
           //Do something here.
        }));
    

    You have to cast the Anonymous delegate as an action otherwise it gets confused ¯\O_o/¯

    If you are using the Async CTP then you can do this

    Application.Current.Dispatcher.InvokeAsync(()=>
        {
           //Do something here.
        });
    
    0 讨论(0)
  • 2020-12-23 17:41

    You are using BGW, it was designed to solve your problem. But you'll have to use it properly, update the collection in a ProgressChanged or RunWorkerCompleted event handler. If that's what you are doing then you created the BGW instance on the wrong thread. It has to be done on the UI thread.

    0 讨论(0)
  • I had the same problem while reloading an observableCollection from an event (on DataReceived) raised by the serial port class. I used MVVM; I tried to update the collection with the BackgroundWorker, but it raised the "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.". I tried many others solutions found online, but the only one that solved my problem (immediately!) was to use a multi-threading observable collection (I used the one in this post: Where do I get a thread-safe CollectionView?)

    0 讨论(0)
  • 2020-12-23 17:48

    If MVVM

    public class MainWindowViewModel : ViewModel {
    
        private ICommand loadcommand;
        public ICommand LoadCommand { get { return loadcommand ?? (loadcommand = new RelayCommand(param => Load())); } }
    
        private ObservableCollection<ViewModel> items;
        public ObservableCollection<ViewModel> Items {
            get {
                if (items == null) {
                    items = new ObservableCollection<ViewModel>();
                }
                return items;
            }
        }
    
        public void Load() {
            BackgroundWorker bgworker = new BackgroundWorker();
            bgworker.WorkerReportsProgress = true;
            bgworker.DoWork += (s, e) => {
                for(int i=0; i<10; i++) {
                    System.Threading.Thread.Sleep(1000);
                    bgworker.ReportProgress(i, new List<ViewModel>());
                }
                e.Result = null;
            };
            bgworker.ProgressChanged += (s, e) => {
                List<ViewModel> partialresult = (List<ViewModel>)e.UserState;
                partialresult.ForEach(i => {
                    Items.Add(i);
                });
            };
            bgworker.RunWorkerCompleted += (s, e) => {
                //do anything here
            };
            bgworker.RunWorkerAsync();
        }
    }
    
    0 讨论(0)
  • 2020-12-23 17:52

    Try This:

    this.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
    () =>
    {
    
     //Code
    
    }));
    
    0 讨论(0)
提交回复
热议问题