De roepingsdraad heeft geen toegang tot dit object omdat een andere draad het bezit

Mijn code is zoals hieronder

public CountryStandards()
{
    InitializeComponent();
    try
    {
        FillPageControls();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Country Standards", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}
/// <summary>
/// Fills the page controls.
/// </summary>
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;
}
/// <summary>
/// Gets the grid data.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="pageIndex">Index of the page.( used in case of paging)   </pamam>
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);
    }
}

De stap objUDMCountryStandards.Country = txtSearchCountry.Text.Trim() != string.Empty ? txtSearchCountry.Text : null;IN GET GET GOD Gegevens werpt uitzondering

De roepingsdraad heeft geen toegang tot dit object omdat een ander
draad bezit het.

Wat is er hier mis?


Antwoord 1, Autoriteit 100%

Dit is een veel voorkomend probleem met mensen aan de slag. Wanneer u uw UI-elementen bijwerkt vanaf een andere draad dan de hoofddraad, moet u gebruiken:

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

U kunt control.Dispatcher.CheckAccess()om te controleren of de huidige draad de besturing bezit. Als het het doet, ziet uw code er normaal uit. Gebruik anders boven het patroon.


Antwoord 2, Autoriteit 7%

Nog een goed gebruik voor Dispatcher.Invokeis voor het onmiddellijk bijwerken van de UI in een functie die andere taken uitvoert:

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

Ik gebruik dit om de knop Tekst naar “-verwerking … ” te updaten en schakel deze uit tijdens het maken van WebClientAANVRAGEN.


Antwoord 3, Autoriteit 6%

Om mijn 2 cent toe te voegen, de uitzondering kan zelfs optreden als u uw code aanroept via System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke().
Het punt is dat je Invoke()moet aanroepen van de Dispatchervan de control waartoe je toegang probeert te krijgen, die in sommige gevallen is het misschien niet hetzelfde als System.Windows.Threading.Dispatcher.CurrentDispatcher. Dus in plaats daarvan zou je YourControl.Dispatcher.Invoke()moeten gebruiken om veilig te zijn. Ik bonkte een paar uur met mijn hoofd voordat ik me dit realiseerde.

Bijwerken

Voor toekomstige lezers lijkt het erop dat dit is veranderd in de nieuwere versies van .NET (4.0 en hoger). U hoeft zich nu geen zorgen meer te maken over de juiste coördinator bij het bijwerken van UI-backing-eigenschappen in uw VM. De WPF-engine rangschikt cross-thread-oproepen op de juiste UI-thread. Bekijk hiermeer details. Met dank aan @aaronburro voor de info en link. Misschien wil je ook ons gesprek hieronder in reacties lezen.


Antwoord 4, autoriteit 5%

Als u dit probleem tegenkomt en UI-besturingselementen zijn gemaakt op een aparte worker-thread bij het werken met BitmapSourceof ImageSourcein WPF, belt u Freeze()methode eerst voordat u de BitmapSourceof ImageSourceals parameter doorgeeft aan een methode. Het gebruik van Application.Current.Dispatcher.Invoke()werkt in dergelijke gevallen niet


Antwoord 5, autoriteit 3%

dit gebeurde met mij omdat ik probeerde access UI-component in another thread insted of UI thread

zoals dit

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

om dit probleem op te lossen, plaatst u elke ui-aanroep in wat Candide hierboven in zijn antwoord noemde

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

Antwoord 6, autoriteit 2%

Om de een of andere reden werkte Candide’s antwoord niet. Het was echter nuttig, omdat het me ertoe bracht dit te vinden, wat perfect werkte:

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

Antwoord 7, autoriteit 2%

Je moet het doen in de UI-thread. Gebruik:

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

Antwoord 8

Dit werkt voor mij.

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

Antwoord 9

Ik ontdekte ook dat System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke()niet altijd de coördinator van doelcontrole is, net zoals dotNet in zijn antwoord schreef. Ik had geen toegang tot de eigen coördinator van de controle, dus gebruikte ik Application.Current.Dispatcheren het probleem was opgelost.


Antwoord 10

Zoals vermeld hier, kan Dispatcher.Invokebevries de gebruikersinterface. Zou in plaats daarvan Dispatcher.BeginInvokemoeten gebruiken.

Hier is een handige extensieklasse om het controleren en aanroepen van de dispatcher te vereenvoudigen.

Voorbeeld van gebruik: (oproep vanuit WPF-venster)

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

Extensieklasse:

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();
        }
    }
}

Antwoord 11

Het probleem is dat je GetGridDataaanroept vanuit een achtergrondthread. Deze methode heeft toegang tot verschillende WPF-besturingselementen die aan de hoofdthread zijn gebonden. Elke poging om ze te openen vanuit een achtergrondthread zal tot deze fout leiden.

Om terug te gaan naar de juiste draad die u moet gebruiken SynchronizationContext.Current.Post. In dit specifieke geval lijkt het echter het meerderheid van het werk dat u aan het doen bent, is UI gebaseerd. Daarom zou je een achtergronddraad maken om onmiddellijk terug te gaan naar de UI-draad en doe wat werk. U moet uw code een beetje een bitformeren, zodat het het dure werk op de achtergronddraad kan doen en vervolgens de nieuwe gegevens naar de UI-draad achteraf moet plaatsen


Antwoord 12

Er zijn absoluut verschillende manieren om dit te doen, afhankelijk van uw behoeften.

One Way Ik gebruik een UI-Updings-thread (dat is niet de hoofd-ui-thread) is om de draad een lus te laten starten waar de gehele logische verwerkingslus wordt aangeroepen op de UI-draad.

Voorbeeld:

public SomeFunction()
{
    bool working = true;
    Thread t = new Thread(() =>
    {
        // Don't put the working bool in here, otherwise it will 
        // belong to the new thread and not the main UI thread.
        while (working)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                // Put your entire logic code in here.
                // All of this code will process on the main UI thread because
                //  of the Invoke.
                // By doing it this way, you don't have to worry about Invoking individual
                //  elements as they are needed.
            });
        }
    });
}

Hiermee wordt de code volledig uitgevoerd op de hoofd-UI-thread. Dit kan een pro zijn voor amateurprogrammeurs die moeite hebben om hun hoofd te wikkelen rond cross-threaded operaties. Het kan echter gemakkelijk een oplichterij worden met complexere gebruikersinterfaces (vooral bij het uitvoeren van animaties). Dit is echt alleen om een systeem te faken dat de gebruikersinterface bijwerkt en vervolgens terugkeert om gebeurtenissen af te handelen die zijn geactiveerd in plaats van efficiënte cross-threading-operaties.


Antwoord 13

Een andere oplossing is ervoor te zorgen dat uw besturingselementen worden gemaakt in de UI-thread, niet door bijvoorbeeld een achtergrondwerkthread.


Antwoord 14

Ik kreeg steeds de foutmelding toen ik trapsgewijze keuzelijsten aan mijn WPF-toepassing toevoegde, en loste de fout op door deze API te gebruiken:

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

Zie voor meer informatie https://msdn.microsoft.com/query/dev14 .Query? AppID = Dev14idef1 & amp; L = EN-US & amp; k = k (system.windows.data.bindingOperations.enablecollectionsynchronisatie); K (TargetFramEworkMoniker-.netFramework, versie% 3DV4.7); K (Devlang-Csharp) & amp; rd = true


Antwoord 15

Soms kan het het object zijn dat u hebt gemaakt die de uitzondering gooit, niet het doelwit waar ik natuurlijk naar keek.

Hier in mijn code:

XAML-bestand:

<Grid Margin="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
    <TextBlock x:Name="tbScreenLog" VerticalAlignment="Stretch" Background="Black" FontSize="12" Foreground="#FF919191" HorizontalAlignment="Stretch"/>
</Grid>

xaml.cs-bestand:

System.Windows.Documents.Run rnLine = new System.Windows.Documents.Run(Message.Item2 + "\r\n");
rnLine.Foreground = LineAlternate ? Brushes.Green : Brushes.Orange;
Dispatcher.Invoke(()=> {
    tbScreenLog.Inlines.Add(rnLine);
});
LineAlternate = !LineAlternate;

Ik kreeg de uitzondering over toegang tot een object van een andere thread, maar ik roepte het aan op de UI-draad ??

Na een tijdje ontmoedigde het op mij dat het niet over het Textblock-object ging, maar over het run-object dat ik heb gemaakt voordat hij oproept.

De code wijzigen in dit opgelost mijn probleem:

Dispatcher.Invoke(()=> {
    Run rnLine = new Run(Message.Item2 + "\r\n");
    rnLine.Foreground = LineAlternate ? Brushes.Green : Brushes.Orange;
    tbScreenLog.Inlines.Add(rnLine);
});
LineAlternate = !LineAlternate;

Other episodes