Invalid cross-thread access

Sep 6, 2011 at 9:21 PM

I am getting a "Invalid cross-thread access" error when RaisePropertyChange is called in NotifyPropertyChangedBase. The property that is raising the error is ModelItemBase.IsUpdating.

I have IsUpdating databound to to a PerformanceProgressBar's visibility property with a bool to visibility converter

This code did not cause any issues in 7.0 but upgraded to 7.1 and this started occuring.

Any idaes?

Sep 7, 2011 at 5:17 AM

Hi Michael -

Well, that means that the RaisePropertyChange call is happening from a non-UI thread.  I'm not sure why the move to 7.1 would be causing this.

Could you post the full call stack that causes that exception?  That might shed some light.  Otherwise, if you can make a simple repro, I can take a look as well.



Sep 7, 2011 at 1:46 PM

here is the full stack trace

  System.Windows.dll!MS.Internal.XcpImports.CheckThread() + 0x21 bytes 
  System.Windows.dll!MS.Internal.XcpImports.GetValue(MS.Internal.IManagedPeerBase managedPeer = {Microsoft.Phone.Controls.PerformanceProgressBar}, System.Windows.DependencyProperty property = {System.Windows.CoreDependencyProperty}) + 0x5 bytes 
  System.Windows.dll!System.Windows.DependencyObject.GetOldValue(System.Windows.DependencyProperty property = {System.Windows.CoreDependencyProperty}, ref System.Windows.EffectiveValueEntry oldEntry = {System.Windows.EffectiveValueEntry}) + 0x8 bytes 
  System.Windows.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.DependencyProperty property = {System.Windows.CoreDependencyProperty}, System.Windows.EffectiveValueEntry oldEntry = {System.Windows.EffectiveValueEntry}, ref System.Windows.EffectiveValueEntry newEntry = {System.Windows.EffectiveValueEntry}, System.Windows.DependencyObject.ValueOperation operation = Reevaluate) + 0x30 bytes 
  System.Windows.dll!System.Windows.DependencyObject.RefreshExpression(System.Windows.DependencyProperty dp = {System.Windows.CoreDependencyProperty}) + 0x10 bytes 
  System.Windows.dll!System.Windows.Data.BindingExpression.RefreshExpression() + 0xc bytes 
  System.Windows.dll!System.Windows.Data.BindingExpression.SendDataToTarget() + 0x64 bytes 
  System.Windows.dll!System.Windows.Data.BindingExpression.SourcePropertyChanged(System.Windows.PropertyPathListener sender = {System.Windows.PropertyPathListener}, System.Windows.PropertyPathChangedEventArgs args = {System.Windows.PropertyPathChangedEventArgs}) + 0xc bytes 
  System.Windows.dll!System.Windows.PropertyPathListener.RaisePropertyPathStepChanged(System.Windows.PropertyPathStep source = {System.Windows.PropertyAccessPathStep}) + 0x42 bytes 
  System.Windows.dll!System.Windows.PropertyAccessPathStep.RaisePropertyPathStepChanged(System.Windows.PropertyListener source = {System.Windows.CLRPropertyListener}) + 0xc bytes 
  System.Windows.dll!System.Windows.CLRPropertyListener.SourcePropertyChanged(object sender = {BuildExplorer.ViewModels.SessionViewModel}, System.ComponentModel.PropertyChangedEventArgs args = {System.ComponentModel.PropertyChangedEventArgs}) + 0x3c bytes 
  System.Windows.dll!System.Windows.Data.WeakPropertyChangedListener.PropertyChangedCallback(object sender = {BuildExplorer.ViewModels.SessionViewModel}, System.ComponentModel.PropertyChangedEventArgs args = {System.ComponentModel.PropertyChangedEventArgs}) + 0x25 bytes 
> AgFx.dll!AgFx.NotifyPropertyChangedBase.RaisePropertyChanged.AnonymousMethod__a(string s = "IsUpdating") Line 268 C#
  AgFx.dll!AgFx.NotifyPropertyChangedBase.RaisePropertyChanged.AnonymousMethod__c() Line 288 + 0x16 bytes C#
  AgFx.dll!AgFx.NotifyPropertyChangedBase.InvokeOnContext(System.Action a = {System.Action}) Line 314 C#
  AgFx.dll!AgFx.NotifyPropertyChangedBase.RaisePropertyChanged(string propertyName = "IsUpdating") Line 288 + 0x12 bytes C#
  AgFx.dll!AgFx.ModelItemBase.IsUpdating.set(bool value = false) Line 124 C#
  AgFx.dll!AgFx.CacheEntry.NotifyCompletion(AgFx.CacheEntry.ValueLoader loader = {AgFx.CacheEntry.LiveValueLoader}, System.Exception ex = {"Invalid cross-thread access."}) Line 802 C#
  AgFx.dll!AgFx.CacheEntry.LiveValueLoader_Failed(object s = {AgFx.CacheEntry.LiveValueLoader}, AgFx.CacheEntry.ExceptionEventArgs e = {AgFx.CacheEntry.ExceptionEventArgs}) Line 622 C#
  AgFx.dll!AgFx.CacheEntry.ValueLoader.OnLoadFailed(System.Exception ex = {"Invalid cross-thread access."}) Line 1183 C#
  AgFx.dll!AgFx.CacheEntry.ValueLoader.FetchData(bool force = false) Line 1104 C#
  AgFx.dll!AgFx.CacheEntry.LoadInternal(bool force = false) Line 748 C#
  AgFx.dll!AgFx.CacheEntry.Load.AnonymousMethod__3() Line 656 + 0x11 bytes C#
  AgFx.dll!AgFx.PriorityQueue.WorkerThread.WorkerThreadProc.AnonymousMethod__4(object s = null) Line 65 + 0xb bytes C#
  mscorlib.dll!System.Threading.ThreadPool.WorkItem.WaitCallback_Context(object state = {System.Threading.ThreadPool.WorkItem}) + 0x18 bytes 
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext = {System.Threading.ExecutionContext}, System.Threading.ContextCallback callback = {System.Threading.ContextCallback}, object state = {System.Threading.ThreadPool.WorkItem}) + 0x63 bytes 
  mscorlib.dll!System.Threading.ThreadPool.WorkItem.doWork(object o = null) + 0x47 bytes 
  mscorlib.dll!System.Threading.Timer.ring() + 0x70 bytes 

Sep 7, 2011 at 9:37 PM

Actually, I think the exception is coming from your DeserializeMethod - it looks like something in there is touching an object on the UI thread, causing this stack.

Another possibility is that you're creating this ModelItemBase off of the UI thread, is that possible?

Sep 9, 2011 at 1:40 PM
Edited Sep 9, 2011 at 2:06 PM

I put a breakpoint at the start of the deserialize method but the exception gets thrown before that.

The view model that is causing the exception (in the IsUpdating RaisePropertyChanged event) has a proxy registered for it. So I removed the proxy registration and the exception goes away. I use the proxy so that when I load a list of sessions to browse I only load a few properties and then when a use views a sessions details it retrieves the additional property values.

The line I commented out was this one: DataManager.Current.RegisterProxy<SessionViewModel>(sessionVM);

I also tried binding to the IsLoading property instead and the exception went way but the IsLoading property appears to never get set to true.

Not sure if that gives you a better sense of what might be happening.


Sep 9, 2011 at 4:23 PM

Hmmm, sort of.   Any chance you could:

1) Whittle this down to a minimal repro?

2) Zip that repro up, open a bug in Issue Tracker, and attach the repro?

With that in hand I can take a look.