20

I am working on a medium size WPF application that utilizes the MVVM pattern. ViewModels use INotifyPropertyChanged to refresh their respective Views.

This approach works perfectly, except for one problem: when this application is left running for long periods of time (3-7 days) the Views (every single View in the entire app!) suddenly stop updating their bound properties.

If I set a breakpoint in the ViewModels, they are chugging away happily, calling PropertyChanged like nothing is wrong. However, if I set a breakpoint in the getter of one of the ViewModel objects that the View is bound to, the getter is never called!

I am stumped at this point, and don't even know how to debug this issue properly. I have checked the Visual Studio output window for data binding errors, but everything looks normal. It is almost as if the WPF data binding engine has crashed in the background. This app is also monitoring unhandled exceptions (AppDomain.UnhandledException and Dispatcher.UnhandledException), but no exceptions are being thrown.

Summary: After long periods of time, the Views stop updating their data bindings, but the ViewModels are still calling the PropertyChanged event.

Any advice???

lokusking
  • 7,396
  • 13
  • 38
  • 57
shansen
  • 317
  • 1
  • 2
  • 12
  • Are there any suspicious entries in the event log? – SvenG Sep 10 '12 at 15:50
  • Are you using oneway data binding? It may cause some problems: http://stackoverflow.com/questions/1389038/why-does-data-binding-break-in-oneway-mode – Jakob Christensen Sep 10 '12 at 15:52
  • 3
    _Any advice?_ - seriously consider making scheduled restarts. WPF is a client tech, I wouldn't so readily expect it to go 24x7. – H H Sep 10 '12 at 15:52
  • Does this problem occur only if the application runs with a debugger attached, or even if it runs stand-alone? – Spontifixus Sep 10 '12 at 15:52
  • @SvenG: No suspicious entries in the EventLog, first thing I did was go through it with a fine tooth comb! – shansen Sep 10 '12 at 16:05
  • @JakobChristensen: I am using one or two oneway data bindings, but I have even removed the Views that they are used on (last week) and the same problem still occurs. – shansen Sep 10 '12 at 16:06
  • @Henk: Unfortunately that won't work for this application, maybe it can do weekly restarts but it can't be restarted every day. – shansen Sep 10 '12 at 16:06
  • @Spontifixus: The problem occurs both stand-alone and with a debugger attached. – shansen Sep 10 '12 at 16:07
  • 1
    Tricky. In that case I would go with @HenkHolterman, though it would be interesting to find out why this occurs in the first place... – Spontifixus Sep 10 '12 at 16:09
  • @Spontifixus - certainly. And maybe it's a small thing and it would be cool if a WPF app could run for a week or longer. I don't have proof either way. – H H Sep 10 '12 at 16:43
  • @shansen - late in the game but I when an app is that critical for that long it ought to be split in a small-as-possible reliable part (service) and the rest. The GUI should be in 'the rest'. – H H Sep 10 '12 at 16:45
  • I appreciate your guys' feedback! Looking through the logs, I can't see any mention of this problem prior to upgrading to .NET Framework 4.5 (several months back). So...the next step is to perform the required code changes and downgrade from .Net 4.5 to 4.0. We'll see if that changes anything! – shansen Sep 10 '12 at 17:23
  • @HenkHolterman: Your suggestion is a good one, and luckily, it is only a nuisance if the screen stops updating, not a life-and-death problem. But still, I'd like to figure out why this is happening! – shansen Sep 10 '12 at 17:27
  • 1
    You might also look at the app while the problem is in effect with [snoop](http://snoopwpf.codeplex.com/) or a similar tool. It helps troubleshoot broken bindings, among other things. I'm not sure what I would expect it to reveal in this situation, but it might shed some light. – default.kramer Sep 10 '12 at 18:00
  • @default.kramer: I have been using Snoop all this morning, and all it shows is that the properties on the ViewModel are not updating, even though the PropertyChanged event is firing. It's as if all of the PropertyChanged listeners have stopped functioning...very strange. – shansen Sep 10 '12 at 18:38
  • 1
    @HenkHolterman: I think i have had WPF applications running for months before, what killed them eventually usually was an [`ExecutionEngineException`](http://msdn.microsoft.com/en-us/library/system.executionengineexception.aspx). – H.B. Sep 10 '12 at 22:44
  • 1
    What is your Working Set Memory looking like for that application? How about Page Faults? – Xcalibur37 Sep 11 '12 at 01:54
  • 1
    @H.B. - could be related, with fewer bindings/updates a few months == a few days. Repeated failure after some length of time hints at a resource leak. – H H Sep 11 '12 at 07:28
  • 1
    Are you using ObservableCollection? When you instantiate the same OC multiple times, the view will get disconnected from the OC and updates will not show anymore. – Michel van Engelen Sep 11 '12 at 10:46
  • Is it happening everywhere or only on a specific machine? – Peter Porfy Sep 11 '12 at 14:17
  • This issue is happening on multiple machines (x64 and x86). Regarding Michel's comment, I did find one place where an ObservableCollection was being instantiated repeatedly at runtime, this bug is now fixed. The biggest help so far was Xcalibur37, who pointed me towards a performance analysis, which after running all night showed a spike and then ramp up of CPU usage and a HUGE number of page faults (nearly 30 million) about 15 minutes before the app stopped updating the screen. I'm going to keep pursuing this line of thought... – shansen Sep 11 '12 at 16:26
  • 1
    OK, I came in this morning and one of the debuggers had tripped on an exception! Woohoo! Here's what we have: System.InvalidOperationException Collection was Modified Call Stack: mscorlib-System.Collections.Generic.List<>.Enumerator.MoveNextRare() PresentationFramework-System.Windows.Data.CollectionView..ctor() . . . System.Windows.DependencyObject.NotifyPropertyChange() So, a property is getting updated, and modifying a collection while the binding is being updated. Now, how the heck can I figure out WHICH binding it is??? – shansen Sep 13 '12 at 14:53
  • I suggest logging the property name in your 'OnPropertyChanged' method. – Timores Sep 20 '12 at 13:46

2 Answers2

3

After several months of debugging, I was finally able to solve the issue by attaching a debugger to the remote target. Only then did it produce an exception that I could debug. I still do not understand why AppDomain.UnhandledException and Dispatcher.UnhandledException did not catch this exception, but at least I was able to figure it out.

shansen
  • 317
  • 1
  • 2
  • 12
  • Can you expand this with more details? – Philip Pittle Dec 03 '14 at 12:33
  • Philip, I wish I had more to give you, but this problem was spooky. I never really understood the root cause, but here are my findings in a bit more detail (see next post). – shansen Dec 03 '14 at 16:58
  • I found that an exception was being thrown in another part of this application when a double value that equaled NaN was converted to a string using .ToString(). I think this exception should have been caught by AppDomain.UnhandledException or Dispatcher.UnhandledException, but for some reason it never was so it took me a while to find it. When this exception was thrown for the first time, the data bindings stopped updating. Obviously something within the data binding framework was crashing, but I don't understand why I didn't get an exception somewhere else to indicate the failure. – shansen Dec 03 '14 at 16:59
  • However, after fixing the cast (I now check for NaN before casting), the data bindings work reliably all the time. I wish I had more to give you, but hopefully this points you in the right direction. – shansen Dec 03 '14 at 16:59
1

You might be falling victim to over-zealous weak references. There might be a fix for your MVVM framework. If not, this information might help you find the issue in the source code.

There is a known memory leak in most implementations of INotifyPropertyChanged. The view model takes a hard reference on the delegate of the XAML control's PropertyChanged handler. That delegate in turn takes a hard reference on the XAML control. Because of this, the control can't be collected as long as the view model exists.

So to fix this problem, many MVVM frameworks use weak references for events. While this can fix the memory leak, it can also cause the problem that you are seeing. If the weak event isn't properly implemented, it might be removed before the XAML control is actually collected.

I suspect that you are using an MVVM framework with weak references, and that they are getting prematurely disposed. To see if this is a likely issue, put a few calls to GC.Collect() and see if the problem occurs more frequently.

Michael L Perry
  • 7,327
  • 3
  • 35
  • 34
  • Thanks for the comment! I am looking into what you said, and trying to trigger the issue by periodically calling GC.Collect(). Your idea about a weak reference getting collected sounds EXACTLY like the symptom I'm seeing...unfortunately I'm not using any external MVVM framework so any bug I find may be within the .NET framework itself. The hardest part about this problem is that it only occurs over days or weeks, so trying to reproduce it is incredibly frustrating. – shansen Sep 12 '12 at 22:05
  • This block might help you (Avoiding a WPF memory leak with DataBinding (Black Magic)): http://blogs.msdn.com/b/micmcd/archive/2008/03/07/avoiding-a-wpf-memory-leak-with-databinding-black-magic.aspx – Morten Frederiksen Sep 15 '12 at 07:26