Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InvalidOperationException("View has been garbage collected.") #2

Closed
Andy360 opened this issue Nov 24, 2015 · 20 comments
Closed

InvalidOperationException("View has been garbage collected.") #2

Andy360 opened this issue Nov 24, 2015 · 20 comments

Comments

@Andy360
Copy link

Andy360 commented Nov 24, 2015

Occasionally, after setting DialogResult = true (or false) in an IModelDialogViewModel using OpenDialog, an exception is thrown from the following location:

public FrameworkElement Source
    {          
    get
        {
            if (!this.IsAlive)
            {
                throw new InvalidOperationException("View has been garbage collected.");
            }
            return (FrameworkElement) this.viewReference.Target;
        }
    }

...that is, for some reason the simple act of setting DialogResult = true leads to a cascade of calls within the MvvmDialogs code that causes the viewReference to be disposed but still modified.

Top of the call stack at the point the exception is thrown:

at MvvmDialogs.Views.ViewWrapper.get_Source()
at MvvmDialogs.DialogServiceViews+<>c__DisplayClass4.b__2(MvvmDialogs.Views.IView)
at System.Linq.Enumerable.Any[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean)
at MvvmDialogs.DialogServiceViews.Unregister(MvvmDialogs.Views.IView)
at MvvmDialogs.DialogServiceViews.OwnerClosed(System.Object, System.EventArgs)
at System.EventHandler.Invoke(System.Object, System.EventArgs)
at System.Windows.Window.OnClosed(System.EventArgs)
at System.Windows.Window.WmDestroy()
at System.Windows.Window.WindowFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.UnsafeSendMessage(IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr)
at System.Windows.Window.InternalClose(Boolean, Boolean)
at System.Windows.Window.Close()
at System.Windows.Window.set_DialogResult(System.Nullable1<Boolean>) at MvvmDialogs.DialogService+<>c__DisplayClass1.<RegisterDialogResult>b__0(System.Object, System.ComponentModel.PropertyChangedEventArgs) at System.ComponentModel.PropertyChangedEventHandler.Invoke(System.Object, System.ComponentModel.PropertyChangedEventArgs) at GalaSoft.MvvmLight.ObservableObject.RaisePropertyChanged(System.String) at LifecycleCRM.UI.ViewModels.InterestedPartyViewModel.set_DialogResult(System.Nullable1)

...which is all happening within the ShowDialog call.

@FantasticFiasco
Copy link
Owner

Thanks for reporting this issue, it is appreciated.

Do you have code you can share, or perhaps create a small application where it is possible to reproduce the exception? I am otherwise somewhat coding in the dark when trying to find the bug you are describing.

Again, thanks!

@Andy360
Copy link
Author

Andy360 commented Nov 25, 2015

Hi, many thanks for your rapid response, it's much appreciated.

There really isn't any meaningful "code to share" - our code is literally just setting DialogResult to true or false in a view model that implements IModalDialogViewModel. Any sample or simple test case will do the same.

To reproduce the issue, simply open and close modal dialogs repeatedly. After doing that a few times (and after a GC occurs while so doing), the problem occurs.

Thanks again.

@FantasticFiasco
Copy link
Owner

Please take a look at my branch where the last commit has modified a coded UI test to constantly use the modal dialog feature. The test will indefinitely open a modal dialog and then close it using a IModalDialogViewModel.

My problem is that the test doesn't throw the exception you stated. Can you please help me by specifying the changes I need to do to the test in order for it to throw the exception you stated?

@Andy360
Copy link
Author

Andy360 commented Nov 26, 2015

Hi, thanks for investigating this. I have spent some time on this today (took a little while to get used to the unfamiliar code) and have not yet been able to reproduce it in your test case. However...

I noticed that the test case was creating the AddTextDialog, but this was not then entering the code path seen in the call stack when it was closed. After some exploration, I determined that this was because the AddTextDialog is not registered with DialogServiceViews, and was able to use this information to narrow down the scope of the problem. In our code, we see the exception thrown when a dialog that can itself be a parent to other dialogs is closed; in your test case, I was able to more closely simulate the situation by adding md:DialogServiceViews.IsRegistered="True" into AddTextDialog.xaml. When the AddTextDialog is closed, it now goes into MvvmDialogs.DialogServiceViews.OwnerClosed etc. as seen in the call stack.

As noted, I've still not been able to cause it to throw. (On the basis that the exception complains that the "View has been garbage collected", it seems likely to be related to GCs and when they happen; I tried allocating arbitrary amounts of memory to try to cause it to GC at the crucial time and trigger the problem, but without success so far). However, registering the AddTextDialog with the service views is at least one step towards reproducing the problem.

I am unfortunately now off work until Tuesday, and will continue investigating then. But since you have been so responsive with your replies, I thought it would be a good idea to update you with my progress. Thanks for your help so far.

@Andy360
Copy link
Author

Andy360 commented Dec 4, 2015

I have spent some more time today attempting to create a reliable repro case in the automated test suite, without success. I appreciate this makes it difficult for you to investigate.

@FantasticFiasco
Copy link
Owner

Unfortunately I haven't had the time myself to investigate the issue further. There is either a bug in my code or in yours. Hopefully I will have some time in the near future to investigate, but it would of course go much quicker if I had a reproducible scenario.

Thank you very much for the time and effort you've put into this.

@bastrakov-sergei
Copy link

Hello,
I am using mvvm dialogs from nuget repository. And i have same error.
Error occurs when application is closing, it does not matter whether the any dialog was opened. I can not reproduce this, but if i can, i will leave the details.

@FantasticFiasco
Copy link
Owner

If both of you are experiencing the same problem I guess it has to be something with MVVM Dialogs. Unfortunate that none of you can reproduce it.

Are you logging in your applications? If so I could perhaps add logging to MVVM Dialogs that you would be able to send be after the issue occurred?

@Andy360
Copy link
Author

Andy360 commented Dec 10, 2015

...either that or we're both making the same mistake. Which I like to think we're not, but is possible. ;-)

Just want to add that we have recently seen it a couple of times on shut-down as well, though closing a dialog is more typical (guess it goes through the same code-path).

Our project is still at a fairly early stage and doesn't have logging set up yet, though it's something we should be adding soon... between that and not having been able to reproduce the problem in your automated test suite, I appreciate this doesn't make it any easier for you to investigate. OTOH, if the logging is in place, we can provide a simple file-logger to it really easily, without needing to set up our entire logging framework.

Thanks for your continued responsiveness, I know how frustrating it can be when users report issues without being able to provide either logs or a repro case!

@FantasticFiasco
Copy link
Owner

I think I can implement something that we can use even though you haven't yourself implemented logging in your application. What I am thinking is something in the lines of:

MvvmDialogs.Logging.Logger.Log = message => Trace.Write(message);

or perhaps if we would like to log to a file:

MvvmDialogs.Logging.Logger.Log = LogToFile;

private static void LogToFile(string message)
{
    using (StreamWriter writer = File.AppendText("log.txt"))
    {
        writer.WriteLine(message);
    }
}

Do you think that would be possible?

@Andy360
Copy link
Author

Andy360 commented Dec 11, 2015

Yes, that would be fine, that's an extension point we can easily attach something to, even if it's just a simple file logger like you show for now.

@FantasticFiasco
Copy link
Owner

I've released v1.2.0. It contains the property MvvmDialogs.Logging.Logger.Writer which you can use for exposing logs from MVVM Dialogs.

Please let me know if you find something useful.

@Andy360
Copy link
Author

Andy360 commented Dec 15, 2015

Not sure how useful it will be, there's not much in there; but the attached is a log from a crash we just observed while shutting down the application.

MvvmDialogs.txt

As before, this threw the "View has been garbage collected" exception shown in the OP.

@FantasticFiasco
Copy link
Owner

I've attempted to fix the issue by investigating the logs. Please download the pre-release NuGet package by writing:

PM> Install-Package MvvmDialogs -Pre

in the Package Manager Console. If your issue is solved, I'll do a new official release.

Thank you again for being very helpful in this issue.

@Andy360
Copy link
Author

Andy360 commented Dec 16, 2015

I've installed the new (pre-release) version... so far so good, but since the issue is intermittent it's hard to guaranteed it's fixed just yet; we'll leave it a few days before giving the all-clear.

Thanks again for your responsiveness.

@FantasticFiasco
Copy link
Owner

Any news regarding this issue?

@Andy360
Copy link
Author

Andy360 commented Jan 4, 2016

Sorry for the lack of update, most of us have been out of the office over the Xmas break. We've still not seen the error happen since your updated build, though as an intermittent issue and the fact not many of us have been around, I'm not sure how compelling that is as evidence of a fix! :-)

@FantasticFiasco
Copy link
Owner

We can wait one more week.

@Andy360
Copy link
Author

Andy360 commented Jan 12, 2016

FYI we've still not seen any further occurrences since installing the pre-release version. Looks like a good fix AFAICT.

Thanks again for your help and responsiveness with this issue, it's much appreciated.

@FantasticFiasco FantasticFiasco mentioned this issue Jan 13, 2016
FantasticFiasco added a commit that referenced this issue Jan 13, 2016
Fixes #2. Preventing throwing exception by pruning the views before unregistering a view.
@FantasticFiasco
Copy link
Owner

Version 1.2.16 has now been released and can be downloaded using NuGet. Thank you very much for your feedback regarding the issue and don't hesitate coming back with more issues you encounter.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants