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

Running Window in another Thread results in a crash #4072

Closed
janwiesemann opened this issue Mar 18, 2021 · 6 comments · Fixed by #4076
Closed

Running Window in another Thread results in a crash #4072

janwiesemann opened this issue Mar 18, 2021 · 6 comments · Fixed by #4076
Labels
Milestone

Comments

@janwiesemann
Copy link
Contributor

janwiesemann commented Mar 18, 2021

After updating to 2.4.4 form 2.4.3 following code stopped working:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        ShutdownMode = ShutdownMode.OnExplicitShutdown;
        StartupUri = null;
        
        base.OnStartup(e);

        //this works
        OpenWindow(false);

        //this does not work
        Thread t = new Thread(() =>
        {
            System.Windows.Threading.Dispatcher disp = System.Windows.Threading.Dispatcher.CurrentDispatcher; //Create new Dispatcher

            try
            {
                OpenWindow(true);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debugger.Break();
            }
            finally
            {
                disp.InvokeShutdown();
            }
        });
        t.SetApartmentState(ApartmentState.STA);
        t.IsBackground = true;
        t.Start();
    }

    private void OpenWindow(bool dialog)
    {
        MetroWindow wind = new MetroWindow();
        wind.Width = 100;
        wind.Height = 100;

        if (dialog)
            wind.ShowDialog();
        else
            wind.Show();
    }
}

Running this results in a InvalidOperationException at

   bei System.Windows.Threading.Dispatcher.VerifyAccess()
   bei System.Windows.Application.add_SessionEnding(SessionEndingCancelEventHandler value)
   bei MahApps.Metro.Behaviors.WindowsSettingBehavior.<AssociatedObject_SourceInitialized>b__2_0() in /_/src/MahApps.Metro/Behaviors/WindowsSettingBehavior.cs:Zeile 55.
   bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   bei System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   bei System.Windows.Threading.DispatcherOperation.InvokeImpl()
   bei System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   bei MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   bei MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   bei System.Windows.Threading.DispatcherOperation.Invoke()
   bei System.Windows.Threading.Dispatcher.ProcessQueue()
   bei System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   bei MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   bei MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   bei System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   bei System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   bei MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   bei MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   bei System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   bei System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   bei System.Windows.Window.ShowHelper(Object booleanBox)
   bei System.Windows.Window.Show()
   bei System.Windows.Window.ShowDialog()
   bei MahError.App.OpenWindow(Boolean dialog) in C:\Users\jan.wiesemann\Desktop\MahError\MahError\App.xaml.cs:Zeile 50.
   bei MahError.App.<OnStartup>b__0_0() in C:\Users\jan.wiesemann\Desktop\MahError\MahError\App.xaml.cs:Zeile 27.

Due to some complex layouts I'm forced to run it in a different Thread. Otherwise all Windows are blocked white WPF initialises the other Window.

@chei90
Copy link

chei90 commented Mar 28, 2021

Holy Shit! That's exactly my problem.

A minimum crashing example from me would be something like this:

var thread = new Thread(() =>
{
	host = new MetroWindow()
	{
		Width = 200,
		Height = 100
	};
	host.Show();
	Dispatcher.Run();

});

thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();

Edit2: Yes, a Downgrade to 2.4.3 circumvents the aforementioned crash.

@NimbusHex
Copy link

It's possible something did change from 2.4.3 to 2.4.4, but this is pretty standard WPF behavior. WPF requires you to be on the dispatcher thread when doing any UI actions. What you guys are doing with Dispatcher is a bit confusing to me, @Jan18101997's dispatcher code wouldn't be doing anything, as the dispatcher isn't being used in any way. @chei-de's Dispatcher.Run() code really does nothing in the context you're using it, host.Show would be causing the exception before you even hit that line of code anyway.

My guess would be that there used to be some sort of "ensure on dispatch thread" code in MetroWindow.Show() that was either taken out or broken in the 2.4.4 release. I'm pretty certain if you (@chei-de) wrap host.Show() in Dispatcher.BeginInvoke, the crash won't occur.

@janwiesemann
Copy link
Contributor Author

It's possible something did change from 2.4.3 to 2.4.4, but this is pretty standard WPF behavior. WPF requires you to be on the dispatcher thread when doing any UI actions. What you guys are doing with Dispatcher is a bit confusing to me, @Jan18101997's dispatcher code wouldn't be doing anything, as the dispatcher isn't being used in any way. @chei-de's Dispatcher.Run() code really does nothing in the context you're using it, host.Show would be causing the exception before you even hit that line of code anyway.

My guess would be that there used to be some sort of "ensure on dispatch thread" code in MetroWindow.Show() that was either taken out or broken in the 2.4.4 release. I'm pretty certain if you (@chei-de) wrap host.Show() in Dispatcher.BeginInvoke, the crash won't occur.

Dispatcher.run starts a new dispatcher inside a new thread.

a change in 2.4.4 broke this. As far as I understand the code at

bei System.Windows.Application.add_SessionEnding(SessionEndingCancelEventHandler value)
   bei MahApps.Metro.Behaviors.WindowsSettingBehavior.<AssociatedObject_SourceInitialized>b__2_0() in /_/src/MahApps.Metro/Behaviors/WindowsSettingBehavior.cs:Zeile 55.

Access application.current.... but in this chase the main application instance is running in a different thread and will result in a crash.

@NimbusHex
Copy link

Dispatcher.run starts a new dispatcher inside a new thread.

Wow, I'm embarrassed to say I never knew this was possible in WPF, I thought you could only have a single Dispatcher per application. Thank you for the info!

@erotavlas
Copy link

erotavlas commented Apr 15, 2021

I'm getting this exact error. My app used to work before however after upgrading to 2.4.4 this happened (except I upgraded from 1.6.0). I guess I'll downgrade to 2.4.3 as mentioned above.

@janwiesemann
Copy link
Contributor Author

I'm getting this exact error. My app used to work before however after upgrading to 2.4.4 this happened (except I upgraded from 1.6.0). I guess I'll downgrade to 2.4.3 as mentioned above.

I've created a pull request for this issue but it was not accepted yet.

If you are upgrading from 1.x make sure to follow there upgrade guide. It's possible, that you have to change some resources as well.

Downgrading to 2.4.3 fixed the issue for me.

@punker76 punker76 added the Bug label Apr 20, 2021
@punker76 punker76 added this to the 2.4.5 milestone Apr 20, 2021
punker76 added a commit that referenced this issue Apr 20, 2021
punker76 added a commit that referenced this issue Apr 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.

5 participants