O segmento de chamada não pode acessar esse object porque um segmento diferente possui

Meu código é como abaixo

public CountryStandards() { InitializeComponent(); try { FillPageControls(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Country Standards", MessageBoxButton.OK, MessageBoxImage.Error); } } ///  /// Fills the page controls. ///  private void FillPageControls() { popUpProgressBar.IsOpen = true; lblProgress.Content = "Loading. Please wait..."; progress.IsIndeterminate = true; worker = new BackgroundWorker(); worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork); worker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(worker_ProgressChanged); worker.WorkerReportsProgress = true; worker.WorkerSupportsCancellation = true; worker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.RunWorkerAsync(); } private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { GetGridData(null, 0); // filling grid } private void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) { progress.Value = e.ProgressPercentage; } private void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) { worker = null; popUpProgressBar.IsOpen = false; //filling Region dropdown Standards.UDMCountryStandards objUDMCountryStandards = new Standards.UDMCountryStandards(); objUDMCountryStandards.Operation = "SELECT_REGION"; DataSet dsRegionStandards = objStandardsBusinessLayer.GetCountryStandards(objUDMCountryStandards); if (!StandardsDefault.IsNullOrEmptyDataTable(dsRegionStandards, 0)) StandardsDefault.FillComboBox(cmbRegion, dsRegionStandards.Tables[0], "Region", "RegionId"); //filling Currency dropdown objUDMCountryStandards = new Standards.UDMCountryStandards(); objUDMCountryStandards.Operation = "SELECT_CURRENCY"; DataSet dsCurrencyStandards = objStandardsBusinessLayer.GetCountryStandards(objUDMCountryStandards); if (!StandardsDefault.IsNullOrEmptyDataTable(dsCurrencyStandards, 0)) StandardsDefault.FillComboBox(cmbCurrency, dsCurrencyStandards.Tables[0], "CurrencyName", "CurrencyId"); if (Users.UserRole != "Admin") btnSave.IsEnabled = false; } ///  /// Gets the grid data. ///  /// The sender. /// Index of the page.( used in case of paging)  private void GetGridData(object sender, int pageIndex) { Standards.UDMCountryStandards objUDMCountryStandards = new Standards.UDMCountryStandards(); objUDMCountryStandards.Operation = "SELECT"; objUDMCountryStandards.Country = txtSearchCountry.Text.Trim() != string.Empty ? txtSearchCountry.Text : null; DataSet dsCountryStandards = objStandardsBusinessLayer.GetCountryStandards(objUDMCountryStandards); if (!StandardsDefault.IsNullOrEmptyDataTable(dsCountryStandards, 0) && (chkbxMarketsSearch.IsChecked == true || chkbxBudgetsSearch.IsChecked == true || chkbxProgramsSearch.IsChecked == true)) { DataTable objDataTable = StandardsDefault.FilterDatatableForModules(dsCountryStandards.Tables[0], "Country", chkbxMarketsSearch, chkbxBudgetsSearch, chkbxProgramsSearch); dgCountryList.ItemsSource = objDataTable.DefaultView; } else { MessageBox.Show("No Records Found", "Country Standards", MessageBoxButton.OK, MessageBoxImage.Information); btnClear_Click(null, null); } } 

A etapa objUDMCountryStandards.Country = txtSearchCountry.Text.Trim() != string.Empty ? txtSearchCountry.Text : null; objUDMCountryStandards.Country = txtSearchCountry.Text.Trim() != string.Empty ? txtSearchCountry.Text : null; em obter dados de grade lança exceção

O segmento de chamada não pode acessar esse object porque um segmento diferente é proprietário dele.

O que há de errado aqui?

Este é um problema comum com pessoas começando. Sempre que você atualizar seus elementos de interface do usuário de um segmento diferente do segmento principal, será necessário usar:

 this.Dispatcher.Invoke(() => { ...// your code here. }); 

Você também pode usar control.Dispatcher.CheckAccess() para verificar se o thread atual possui o controle. Se ele for o proprietário, seu código parecerá normal. Caso contrário, use o padrão acima.

Outro bom uso para Dispatcher.Invoke é para atualizar imediatamente a interface do usuário em uma function que executa outras tarefas:

 // Force WPF to render UI changes immediately with this magic line of code... Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle); 

Eu uso isso para atualizar o texto do botão para ” Processando … ” e desabilitá-lo ao fazer solicitações de WebClient .

Para adicionar meus 2 centavos, a exceção pode ocorrer mesmo se você chamar seu código através de System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke() .
O ponto é que você tem que chamar Invoke() do Dispatcher do controle que você está tentando acessar , que em alguns casos pode não ser o mesmo que System.Windows.Threading.Dispatcher.CurrentDispatcher . Então, ao invés disso, você deve usar YourControl.Dispatcher.Invoke() para estar seguro. Eu estava batendo minha cabeça por algumas horas antes de perceber isso.

Se alguém tentar trabalhar com o BitmapSource no WPF e nos threads e tiver esta mesma mensagem: basta chamar o método Freeze() antes de passar um BitmapSource como um parâmetro de thread.

isso aconteceu comigo porque eu tentei access UI componente de access UI em another thread insted of UI thread

como isso

 private void button_Click(object sender, RoutedEventArgs e) { new Thread(SyncProcces).Start(); } private void SyncProcces() { string val1 = null, val2 = null; //here is the problem val1 = textBox1.Text;//access UI in another thread val2 = textBox2.Text;//access UI in another thread localStore = new LocalStore(val1); remoteStore = new RemoteStore(val2); } 

para resolver esse problema, envolva qualquer ui call dentro do que Candide mencionou acima em sua resposta

 private void SyncProcces() { string val1 = null, val2 = null; this.Dispatcher.Invoke((Action)(() => {//this refer to form in WPF application val1 = textBox.Text; val2 = textBox_Copy.Text; })); localStore = new LocalStore(val1); remoteStore = new RemoteStore(val2 ); } 

Você precisa atualizar para a interface do usuário, então use

 Dispatcher.BeginInvoke(new Action(() => {GetGridData(null, 0)})); 

Por alguma razão, a resposta de Candide não foi construída. Foi útil, no entanto, como me levou a encontrar isso, que funcionou perfeitamente:

 System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke((Action)(() => { //your code here... })); 

O problema é que você está chamando GetGridData de um thread em segundo plano. Este método acessa vários controles do WPF que estão vinculados ao thread principal. Qualquer tentativa de acessá-los a partir de um thread em segundo plano levará a esse erro.

Para voltar ao segmento correto, você deve usar SynchronizationContext.Current.Post . No entanto, neste caso em particular, parece que a maioria do trabalho que você está fazendo é baseado em interface do usuário. Portanto, você criaria um thread de plano de fundo apenas para voltar imediatamente ao thread da interface do usuário e fazer algum trabalho. Você precisa refatorar seu código um pouco para que ele possa fazer o trabalho caro no encadeamento em segundo plano e depois publicar os novos dados no encadeamento de interface do usuário posteriormente

Eu também achei que System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke() nem sempre é despachante de controle de destino, exatamente como o dotNet escreveu em sua resposta. Eu não tive access ao próprio despachante do controle, então usei o Application.Current.Dispatcher e resolvi o problema.

Além disso, outra solução é garantir que seus controles sejam criados no thread da interface do usuário, não por um thread de trabalho em segundo plano, por exemplo.

Como mencionado aqui , o Dispatcher.Invoke pode congelar a interface do usuário. Deve usar Dispatcher.BeginInvoke vez disso.

Aqui está uma class de extensão útil para simplificar a chamada de dispatcher de verificação e chamada.

Uso de amostra: (chamada da janela do WPF)

 this Dispatcher.InvokeIfRequired(new Action(() => { logTextbox.AppendText(message); logTextbox.ScrollToEnd(); })); 

Classe de extensão:

 using System; using System.Windows.Threading; namespace WpfUtility { public static class DispatcherExtension { public static void InvokeIfRequired(this Dispatcher dispatcher, Action action) { if (dispatcher == null) { return; } if (!dispatcher.CheckAccess()) { dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle); return; } action(); } } } 

Isso funciona para mim.

  new Thread(() => { Thread.CurrentThread.IsBackground = false; Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate { //Your Code here. }, null); }).Start(); 

Continuei recebendo o erro quando adicionei comboboxes em cascata ao meu aplicativo WPF e resolvi o erro usando esta API:

  using System.Windows.Data; private readonly object _lock = new object(); private CustomObservableCollection _myUiBoundProperty; public CustomObservableCollection MyUiBoundProperty { get { return _myUiBoundProperty; } set { if (value == _myUiBoundProperty) return; _myUiBoundProperty = value; NotifyPropertyChanged(nameof(MyUiBoundProperty)); } } public MyViewModelCtor(INavigationService navigationService) { // Other code... BindingOperations.EnableCollectionSynchronization(AvailableDefectSubCategories, _lock ); } 

Para obter detalhes, consulte https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Windows.Data.BindingOperations.EnableCollectionSynchronization);k(TargetFrameworkMoniker-.NETFramework, Version % 3Dv4.7); k (DevLang-csharp) & rd = true