dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.28k stars 1.76k forks source link

[Bug] [WinUI] [Essentials] When calling MainThread, System.InvalidOperationException: 'Unable to find main thread.' #2451

Closed drasticactions closed 2 years ago

drasticactions commented 3 years ago

Description

image

When calling MainThread.BeginInvokeOnMainThread or MainThread.InvokeOnMainThreadAsync on WinUI from a background thread, the dispatcher will be null. When it's invoked from the UI Thread, it does work.

Steps to Reproduce

Run this sample project, click on the DisplayPromptAsync prompt, and dismiss the prompt. The code-behind runs a background task and invokes MainThread to update the UI. It works on Android and iOS, but fails in WinUI. MauiWinUITest.zip

Workaround

In MAUI Main and Preview 11+ builds, if you use the Dispatcher on Maui Elements or the Application (Ex. Application.Current.Dispatcher.Dispatch()), it was fixed and does work.

However, MauiEssentials was not updated to the new API, and that still fails.

mattleibow commented 3 years ago

This is fixed in Controls/Core with #2862 since we reworked that.

And, we probably need to remove MainThread from essentials because it make no sense because windows has no root window and there may be multiple threads, each with a window. So which to pick?

alexeystrakh commented 3 years ago

Same issue with the MainThread, the following works:

Application.Current.Dispatcher.BeginInvokeOnMainThread(action)
drasticactions commented 2 years ago

This is fixed in Controls/Core with #2862 since we reworked that.

And, we probably need to remove MainThread from essentials because it make no sense because windows has no root window and there may be multiple threads, each with a window. So which to pick?

I would support that. Since it's still there, IMO, I would keep this bug open. When it's removed or refactored, then it can be closed.

wenwen60 commented 2 years ago

Reproduce on Windows with VS2022 17.2.0 Preview 2.0 [32215.517.main], attach the repro sample MauiApp3.zip

knocte commented 2 years ago

Same issue with the MainThread, the following works: Application.Current.Dispatcher.BeginInvokeOnMainThread(action)

I guess you meant Application.Current.Dispatcher.Dispatch(action) because I don't find the method BeginInvokeOnMainThread in that Dispatcher class, right @alexeystrakh? This workaround works for me. In particular, I created this (ugly) helper in my code:

    private void SafeInvokeInMainThread(Action action)
    {
        if (DeviceInfo.Platform == DevicePlatform.WinUI)
        {
            Application.Current.Dispatcher.Dispatch(action);
        }
        else
        {
            MainThread.BeginInvokeOnMainThread(action);
        }
    }

However, take in account that this is not needed always. For example, calling MainThread.BeginInvokeOnMainThread works fine for me if I call it from an OnButtonClicked delegate for example, but if I call it from an OnAppearing() event, then I find the InvalidOperationException.

@mattleibow let me know if you need a testcase project? and I will upload it; but I guess you already reproduced it, as it seems very easy to stumble upon it. BTW I hope this gets fixed before GA? I see the milestone marked in this bug is outdated AFAIU. And FYI this is my setup where I still reproduce it:

>dotnet workload list

Installed Workload Ids      Installation Source
-----------------------------------------------
maui-windows                VS 17.2.32314.265
maui-maccatalyst            VS 17.2.32314.265
maccatalyst                 VS 17.2.32314.265
maui-ios                    VS 17.2.32314.265
ios                         VS 17.2.32314.265
maui-android                VS 17.2.32314.265
android                     VS 17.2.32314.265
drasticactions commented 2 years ago

When they wrote that comment, Dispatcher.BeginInvokeOnMainThread existed. It was replaced and renamed with IDispatcher.Dispatch in newer builds.

This should be fixed with https://github.com/dotnet/maui/issues/5671.