429

My code is as below

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

The step objUDMCountryStandards.Country = txtSearchCountry.Text.Trim() != string.Empty ? txtSearchCountry.Text : null; in get grid data throws exception

The calling thread cannot access this object because a different thread owns it.

What's wrong here?

Christos
  • 53,228
  • 8
  • 76
  • 108
Kuntady Nithesh
  • 11,371
  • 20
  • 63
  • 86
  • 6
    possible duplicate of http://stackoverflow.com/questions/2728896/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it , http://stackoverflow.com/questions/3146942/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it , http://stackoverflow.com/questions/7684206/threading-issue-the-calling-thread-cannot-access-this-object-because-a-differen , http://stackoverflow.com/questions/8950347/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it –  Mar 16 '12 at 06:21

15 Answers15

855

This is a common problem with people getting started. Whenever you update your UI elements from a thread other than the main thread, you need to use:

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

You can also use control.Dispatcher.CheckAccess() to check whether the current thread owns the control. If it does own it, your code looks as normal. Otherwise, use above pattern.

oddRaven
  • 672
  • 1
  • 7
  • 20
Candide
  • 30,469
  • 8
  • 53
  • 60
  • 3
    I have the same problem as OP; My problem now is that the event causes now a stack overflow. :\ – Malavos Jan 22 '14 at 12:14
  • 2
    Went back to my old project and solved this. Also, I had forgotten to +1 this. This method works quite well! It improve my application loading time on 10seconds or even more, just by using threads to load our localized resources. Cheers! – Malavos May 07 '14 at 13:21
  • 4
    If I'm not wrong you can't even read a UI object from a non-owner thread; surprised me a bit. – Elliot Mar 02 '15 at 09:25
  • 49
    `Application.Current.Dispatcher.Invoke(MyMethod, DispatcherPriority.ContextIdle);` to get the dispatcher if not on the UI thread as per [this answer](http://stackoverflow.com/a/16904930/345659) – JumpingJezza Aug 21 '15 at 02:59
  • 4
    +1. Ha! I used this for some WPF hackery to keep things decoupled. I was in a static context so I couldn't use `this.Dispatcher.Invoke`.... instead... `myControl.Dispatcher.Invoke` :) I needed to return an object back so I did `myControlDispatcher.Invoke(() => myControl.DataContext)`; – C. Tewalt Feb 14 '16 at 07:20
  • @nikotromus I don't see any _condescension_. This **is** a common problem with people getting started. If it did imply anything, it would be that developers ought to **learn** a bit about the UI-thread, the Dispatchers, how a WPF application runs and what cross-thread operations are **before** beginning to use thread-based operations and capabilities. The first sentence simply translates to: _Sometimes, you cannot (re)produce a working example if you don't know the important details_ (which is the case when people are getting started). – Vector Sigma Oct 09 '19 at 17:44
  • @Elliot you are not wrong and it does make sense.. the object still belongs to the other thread so to get properties you need an instance on the relevant thread – MwBakker Feb 19 '20 at 08:42
  • I had problems with that code. I would rather recommend, **Application.Current.Dispatcher.Invoke(...)** – I.Step May 28 '20 at 21:00
  • This still does not work. Somehow my system is pigheadedly refusing to accept invokes, be it the application, element, or parent elements. – Rafael Ventura Aug 31 '20 at 19:05
60

To add my 2 cents, the exception can occur even if you call your code through System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke().
The point is that you have to call Invoke() of the Dispatcher of the control that you're trying to access, which in some cases may not be the same as System.Windows.Threading.Dispatcher.CurrentDispatcher. So instead you should use YourControl.Dispatcher.Invoke() to be safe. I was banging my head for a couple of hours before I realized this.

Update

For future readers, it looks like this has changed in the newer versions of .NET (4.0 and above). Now you no longer have to worry about the correct dispatcher when updating UI-backing properties in your VM. WPF engine will marshal cross-thread calls on the correct UI thread. See more details here. Thanks to @aaronburro for the info and link. You may also want to read our conversation below in comments.

Update 2

Since this is a popular post now, I thought I'd share my experience that I had in the following years. The behavior seems to be that any property bindings will update correctly in cross-thread calls (no marshalling required; WPF will handle it for you). OTOH command bindings will need to be delegated to the UI dispatcher. I have tested it with both MVVM Light and the relatively new Community Toolkit and it seems to be the case with both the old Framework and the new .NET 5 and 6. AsyncRelayCommand fails to update the UI when invoked from non-UI thread (This happens when CanExecuteChanged is fired from a worker thread which updates, for example, button's Enabled property). The solution of course is to store UI dispatcher somewhere in the global space in your VM upon startup and then use it when updating the UI.

dotNET
  • 33,414
  • 24
  • 162
  • 251
  • Naaah... If this holds true, you cannot use MVVM where you simply have no knowledge of the control's dispatcher. Obviously, that would break thousands of applications world wide. Please eloborate on this. Do you have a sample project that demonstrates this issue? Source on MSDN? To add some more cents, I'd say that `BeginInvoke` is to be used when `Invoke` seems to fail (usually due to some `WPF` focus/layout/rendering weirdness). – l33t Sep 27 '16 at 08:36
  • 5
    @l33t: WPF supports multiple UI threads in one application, each of which will have its own `Dispatcher`. In those cases (which are admittedly rare), calling `Control.Dispatcher` is the safe approach. For reference you can see [this article](https://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/) as well as [this SO post](http://stackoverflow.com/questions/4620818/wpf-threading-dispatcher-static-vs-dispatcher-on-a-control) (particularly Squidward's answer). – dotNET Sep 27 '16 at 10:13
  • 1
    Interestingly, I was facing this very exception when I googled and landed on this page and like most of us do, tried the highest voted answer, which didn't solve my issue then. I then found out this reason and posted it here for peer developers. – dotNET Sep 27 '16 at 10:15
  • This is true, you should at least use `Application.Current.Dispatcher` if you can't get control's dispatcher. – Tyrrrz Nov 16 '17 at 13:55
  • 1
    @l33t, if you are using MVVM correctly, then it shouldn't be a problem. The view necessarily know what Dispatcher it is using, whilehe ViewModels and Models know nothing of controls and have no need to know of controls. – aaronburro Feb 23 '18 at 14:54
  • @aaronburro, so how would the viewmodel get hold of the control's dispatcher? Using behaviors and stuff? It's certainly tempting to use `Application.Current.Dispatcher` in which case you may run in to weird problems as pinpointed by this answer. – l33t Feb 23 '18 at 16:35
  • 2
    @aaronburro: Problem is that VM may want to launch actions on alternate threads (e.g. Tasks, Timer-based actions, Parallel queries), and as the operation progresses, may like to update UI (through RaisePropertyChanged etc), which will in turn try to access a UI control from non-UI thread and thus result in this exception. I don't know of a *correct MVVM approach* that would solve this problem. – dotNET Feb 24 '18 at 08:39
  • 1
    The WPF binding engine automatically marshals property change events to the correct Dispatcher. This is why VM has no need to know of the Dispatcher; all it has to do is just raise property changed events. WinForms binding is a different story. – aaronburro Aug 17 '18 at 20:31
  • @aaronburro consider when you want to have some sort of OnRefresh callback (when the user refreshes the screen) and you want to load the elements in some background thread while displaying a progress bar in the front so that the UI doesn't end up freezing. This is more than just raising property changed events, you want to also properly load your models and their associated wrappers (i.e collections, ienumerables, etc) – Matthew S Feb 27 '19 at 16:18
  • @aaronburro: This is simply incorrect. 500+ upvotes of the accepted answer indicate something :). – dotNET Feb 28 '19 at 01:56
  • @MatthewS, I may be misunderstanding you, but why are you using a callback for that? If the user clicks a button (or does a keystroke or gesture), that should be handled via a Command on the VM. The VM code then starts a new thread or Task. As you are loading and progress is updated, call PropertyChanged for whatever your progress property is. When whatever you are loading is complete, you raise a PropertyChanged notification for whatever the screen needs to show. For all of these notifications, WPF marshals to the correct thread. – aaronburro Mar 26 '19 at 13:06
  • @dotNET: It's not about if the chosen answer is "correct." Sure, that's how you invoke to the Dispatcher. It's about whether your ViewModels should even know about it. In a properly structured MVVM program, they should not. Every single VM that I've seen hitting the Dispatcher directly had improperly coupled itself to the view. – aaronburro Mar 26 '19 at 13:17
  • @aaronburro: Ah I see. My earlier impression was that you were suggesting that one could simply issue a `PropertyChanged` from anywhere in the VM layer and WPF would correctly marshal bindings to the UI thread, so I clarified that this was simply not the case. As of whether we *should* avoid such cross-thread UI updates in our application design is a different question, read my next comment please (not enough space here). – dotNET Mar 26 '19 at 14:23
  • @aaronburro: With async/multi-threaded solutions, you eventually have to somehow delegate calls from a non-UI thread to the UI thread, one way or the other. My favorite MVVM Library (MVVM Light) actually contains a built-in helper function that allows me to delegate calls to the UI thread. So I don't think it's about whether one should or shouldn't; one has to. – dotNET Mar 26 '19 at 14:25
  • WPF absolutely marshals `INotifyPropertyChanged.PropertyChanged` to the appropriate UI thread (https://stackoverflow.com/questions/1321423/does-wpf-databinding-marshall-changes-to-the-ui-thread). `INotifyCollectionChanged.CollectionChanged` is different, as it DOES have UI thread affinity, but that is a different beast, with a different solution (SynchronizationContexts). But, implementation of that interface should NOT be written into a VM. It should instead be in a specialized class. – aaronburro Mar 26 '19 at 17:07
  • @aaronburro: Thanks for the link. I must say it is a surprise for me, but looking at the content of that page I see that I'm not alone. Many other people also thought/had read literature that suggested what I said above. In my case I had 3 reasons to believe what I said; 1. I had read it, 2. I had seen WPF throw exception when I updated a UI-backing property from a timer event, 3. MVVM Light contains a special method to marshal cross-thread calls. Looks like this has changed somewhere around .NET 4.0 as suggested by someone on your link and [here](https://stackoverflow.com/questions/29485421). – dotNET Mar 26 '19 at 18:07
  • 1) Do you remember where you read it? I know I used WPF in 3.5 and don't recall having issues with it there. I don't have VS installed on my home machine, otherwise I'd run it under different compilers and see what happens. WinForms binding, for sure, doesn't marshal. 2) Are you sure it wasn't an ObservableCollection method that threw it? – aaronburro Mar 26 '19 at 18:19
  • 1
    @aaronburro: I can't recall the exact articles I read, but here is [a 2014 post](https://msdn.microsoft.com/en-us/magazine/dn630646.aspx) that says exactly what I believed before. See how he needs to marshal his scalar property change notification to avoid application crash. I too have experienced this in the past, so it must be something that has changed in the last few .NET versions. – dotNET Mar 26 '19 at 18:27
  • From that, it looks like Silverlight/WindowsPhone is the issue. I also wouldn't use their "solution," as you have pointed out that you have to call the *correct* Dispatcher. Seems like if you want to share VMs across XAML frameworks, you've got more work to do. – aaronburro Mar 26 '19 at 18:40
  • @aaronburro: [More on the same](https://www.codeproject.com/Articles/756665/How-To-Simplify-the-Use-of-Threads-in-WPF). Doesn't look like the problem was confined to Windows Phone or SilverLight. As I said, I have experienced this problem in a desktop app where I had to update (scalar) properties of my VM from a timer event, and have been using MVVM Light's built-in method to mitigate it ever since then, so much so that I didn't even bother to check it again. Now that we know you're correct about it at least for .NET 4.0 or above, I'll see if I can eventually get rid of this habit. :) – dotNET Mar 27 '19 at 04:08
  • eh, the "edit" section doesn't apply in all cases. If you use `Task.Factory...` you can have `Dispatcher.CurrentDispatcher` (within the task) be the wrong dispatcher for the UI thread and still get this error. The fix (one possible fix) is to save a reference to the correct dispatcher before the task starts. – BurnsBA Oct 14 '22 at 13:00
  • Your bit about Command Bindings in Update 2 led me to solve my issue. Many thanks! – NobleGuy Mar 20 '23 at 17:50
46

If you encounter this problem and UI Controls were created on a separate worker thread when working with BitmapSource or ImageSource in WPF, call Freeze() method first before passing the BitmapSource or ImageSource as a parameter to any method. Using Application.Current.Dispatcher.Invoke() does not work in such instances

Smith Kare
  • 5
  • 1
  • 3
juFo
  • 17,849
  • 10
  • 105
  • 142
  • 37
    Ah, nothing like a good old vague and mysterious trick to solve something nobody understands. – Edwin Mar 04 '17 at 10:43
  • 2
    I'd love more information about why this works and how I could have figured it out myself. – Xavier Shay Feb 28 '18 at 17:45
  • @XavierShay https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/freezable-objects-overview – juFo Mar 01 '18 at 10:36
33

this happened with me because I tried to access UI component in another thread insted of UI thread

like this

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

to solve this problem, wrap any ui call inside what Candide mentioned above in his answer

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 );
}
Community
  • 1
  • 1
Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
  • 2
    Upvoted, because this is ***not*** a duplicate answer or plagiaristic, but it instead provides a good example that other answers were lacking, while giving credit for what was posted earlier. – Panzercrisis Sep 02 '16 at 15:24
  • Upvote is for a clear answer. Although same was written by others, but this make it clear for anyone who is stuck. – NishantM Mar 04 '17 at 07:11
21

You need to do it on the UI thread. Use:

Dispatcher.BeginInvoke(new Action(() => {GetGridData(null, 0)})); 
Pang
  • 9,564
  • 146
  • 81
  • 122
VikramBose
  • 303
  • 2
  • 10
15

For some reason Candide's answer didn't build. It was helpful, though, as it led me to find this, which worked perfectly:

System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke((Action)(() =>
{
   //your code here...
}));
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
Sarah
  • 301
  • 1
  • 3
  • 7
  • It's possible that you didn't call from the form's class. Either you can grab a reference to the Window, or you can probably use what you suggested. – Simone Nov 12 '15 at 11:05
  • 9
    If it worked for you, it was unnecessary to use it in the first place. `System.Windows.Threading.Dispatcher.CurrentDispatcher` is *the dispatcher for the current thread*. That means if you're on a background thread, it's **not** going to be the UI thread's dispatcher. To access the UI thread's dispatcher, use `System.Windows.Application.Current.Dispatcher`. –  Sep 01 '17 at 14:46
6

This works for me.

new Thread(() =>
        {

        Thread.CurrentThread.IsBackground = false;
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate {

          //Your Code here.

        }, null);
        }).Start();
nPcomp
  • 8,637
  • 2
  • 54
  • 49
5

As mentioned here, Dispatcher.Invoke could freeze the UI. Should use Dispatcher.BeginInvoke instead.

Here is a handy extension class to simplify the checking and calling dispatcher invocation.

Sample usage: (call from WPF window)

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

Extension class:

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();
        }
    }
}
Jeson Martajaya
  • 6,996
  • 7
  • 54
  • 56
4

I also found that System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke() is not always dispatcher of target control, just as dotNet wrote in his answer. I didn't had access to control's own dispatcher, so I used Application.Current.Dispatcher and it solved the problem.

Paulus Limma
  • 432
  • 6
  • 10
3

There are definitely different ways to do this depending on your needs.

One way I use a UI-updating thread (that's not the main UI thread) is to have the thread start a loop where the entire logical processing loop is invoked onto the UI thread.

Example:

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

With this, code executes entirely on main UI thread. This can be a pro for amateur programmers that have difficulty wrapping their heads around cross-threaded operations. However, it can easily become a con with more complex UIs (especially if performing animations). Really, this is only to fake a system of updating the UI and then returning to handle any events that have fired in lieu of efficient cross-threading operations.

Jonathan Plumb
  • 417
  • 1
  • 4
  • 12
3

The problem is that you are calling GetGridData from a background thread. This method accesses several WPF controls which are bound to the main thread. Any attempt to access them from a background thread will lead to this error.

In order to get back to the correct thread you should use SynchronizationContext.Current.Post. However in this particular case it seems like the majority of the work you are doing is UI based. Hence you would be creating a background thread just to go immediately back to the UI thread and do some work. You need to refactor your code a bit so that it can do the expensive work on the background thread and then post the new data to the UI thread afterwards

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
1

Sometimes it can be the object you created that throws the exception, not the target where I was obviously looking at.

In my code here:

xaml file:

<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 file:

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;

I got the exception about accessing an object from a different thread but I was invoking it on the UI thread??

After a while it daunted on me that it was not about the TextBlock object but about the Run object I created before invoking.

Changing the code to this solved my problem:

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

Also, another solution is ensuring your controls are created in UI thread, not by a background worker thread for example.

FindOutIslamNow
  • 1,169
  • 1
  • 14
  • 33
0

I kept getting the error when I added cascading comboboxes to my WPF application, and resolved the error by using this API:

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

    }

For details, please see 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

user8128167
  • 6,929
  • 6
  • 66
  • 79
0

I encountered this error strangely on the second item selected from a WPF Control.

The reason was that I loaded the data into a RX SourceCache, and the loaded elements had ObservableCollections as Navigation Properties wrapped into a CollectionView. The ObservableCollections are connected to the UIThread and the data was loaded by the WorkerThread. As the CollectionView was only populated on displaying the first element, the issue with the different thread only occured on the second item being selected.

Solution would be to move the sublists to the ViewModel as ReadOnlyObservableCollections and filter the full list of the sub element table by the currently selected main element.

RonnyR
  • 210
  • 1
  • 5