MaterialDesignInXamlToolkit icon indicating copy to clipboard operation
MaterialDesignInXamlToolkit copied to clipboard

DialogHost can throw exception when opening and closing dialog in quick succession

Open mgnslndh opened this issue 5 years ago • 0 comments

DialogHost can throw exception when opening and closing dialog in quick succession.

Background

I have a view which is password protected. The password dialog is shown when the user opens the view. The dialog is using a DialogHost placed on the view and is the only "client" of the dialog host. If the user navigates away from the view, the dialog will be closed.

Problem

If the dialog is shown and the user navigates away from the view shortly after there is a chance that the DialogHost will throw a NullReferenceException.

2018-10-04 09:02:10.870 +02:00 [Error      ] [02] Unhandled exception occurred. Origin=System.Threading.Tasks.TaskScheduler.UnobservedTaskException, 
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at MaterialDesignThemes.Wpf.DialogHost.<>c__DisplayClass38_1.<IsOpenPropertyChangedCallback>b__2(Task t) in C:\projects\materialdesigninxamltoolkit\MaterialDesignThemes.Wpf\DialogHost.cs:line 296
   at System.Threading.Tasks.ContinuationResultTaskFromTask`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at MaterialDesignThemes.Wpf.DialogHost.<>c__DisplayClass38_1.<IsOpenPropertyChangedCallback>b__2(Task t) in C:\projects\materialdesigninxamltoolkit\MaterialDesignThemes.Wpf\DialogHost.cs:line 296
   at System.Threading.Tasks.ContinuationResultTaskFromTask`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()<---

My guess is that since there is a delay when opening a dialog it is possible that some reference become null during the delay. I think that the child variable should not change value but it could be possible that its Dispatcher property becomes null when the object is removed from visual tree or something like that.

Anyway, the code might need some more protective null checking.

dialogHost.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
    CommandManager.InvalidateRequerySuggested();
    UIElement child = dialogHost.FocusPopup();

    if (child != null)
    {
        //https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/issues/187
        //totally not happy about this, but on immediate validation we can get some weird looking stuff...give WPF a kick to refresh...
        Task.Delay(300).ContinueWith(t => child.Dispatcher.BeginInvoke(new Action(() => child.InvalidateVisual())));
    }
}));

see DialogHost.cs

mgnslndh avatar Oct 04 '18 07:10 mgnslndh