CommunityToolkit / Microsoft.Toolkit.Win32

ARCHIVE - This repository contained XAML Islands wrapper controls and tooling for XAML Islands with WinUI 2, see readme for more info about XAML Islands with WinUI 3 and the WindowsAppSDK.
https://aka.ms/windowsappsdk
Other
384 stars 89 forks source link

Thread marshall exception when using Windows.UI.Xaml.Media and XAML Islands in same app #304

Open JaykeBird opened 3 years ago

JaykeBird commented 3 years ago

Describe the bug

When trying to access a Windows.UI.Xaml.Media class for the InkToolbar, in a XAML Islands WPF app, I got the Exception 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))' immediately during runtime.

The code in question triggering this was just a Windows.UI.Xaml.Media.BrushCollection that I had created in the code-behind.

I was attempting to recreate Scenario 2 from the SimpleInk sample project, with the custom CalligraphyPen button. If I put the BrushCollection in XAML, as they do in the sample, then this error occurs at build time rather than runtime.

Steps to Reproduce

Steps to reproduce the behavior:

  1. Create WPF app, targetting .NET Core 3.1.
  2. Setup InkToolbar and InkCanvas controls via XAML Islands, as done in the example in Microsoft Docs.
  3. Reference the Microsoft.Windows.SDK.Contracts NuGet package (version 10.0.18362.2005).
  4. In the code-behind file of the window (MainWindow.xaml.cs), implement the BrushCollection from the SimpleInk sample project - Scenario 2 in C# (see screenshot below). This can be put in the constructor or done as a field in the class itself.
  5. Start debugging

Expected behavior

I expected the BrushCollection to be created with no problem, and then I'd be able to utilize it in code later on.

Screenshots

If applicable, add screenshots to help explain your problem. image

Environment

NuGet Package(s): Microsoft.Toolkit.Wpf.UI.Controls v6.1.2, Microsoft.Windows.SDK.Contracts v10.0.18362.2005

Project .NET Version:
- [ ] .NET Framework (version: )
- [ ] .NET Core 3
- [x] .NET Core 3.1 (version: latest)

Windows 10 Build Number:
- [ ] Fall Creators Update (16299)
- [ ] April 2018 Update (17134)
- [ ] October 2018 Update (17763)
- [ ] May 2019 Update (18362)
- [x] Version 1909 (18363)
- [ ] Insider Build (build number: )

App min and target version:
- [ ] Fall Creators Update (16299)
- [ ] April 2018 Update (17134)
- [ ] October 2018 Update (17763)
- [x] May 2019 Update (18362)
- [ ] Insider Build (xxxxx)

Device form factor:
- [x] Desktop
- [ ] Xbox
- [ ] Surface Hub
- [ ] IoT

Visual Studio 
- [ ] 2017 (version: )
- [x] 2019 (version: 16.8.3) 
- [ ] 2019 Preview (version: )

Additional context

Add any other context about the problem here.

ghost commented 3 years ago

Hello JaykeBird, thank you for opening an issue with us!

I have automatically added a "needs triage" label to help get things started. Our team will analyze and investigate the issue, and escalate it to the relevant team if possible. Other community members may also look into the issue and provide feedback 🙌

michael-hawker commented 3 years ago

FYI @marb2000

JaykeBird commented 3 years ago

Update / additional info:

I was able to work around this, but the way to do so is a lot of extra work and is fairly limiting. However, perhaps this may offer some additional insight about this issue?

If I - rather than using the InkToolbar and InkCanvas classes included with the Microsoft.Toolkit.Wpf.UI.Controls - used a WindowsXamlHost and hooked into the WindowsXamlHost's ChildChanged event, I can access and use the BrushCollection or any other Media class inside that ChildChanged event handler without issue.

You can use this setup in this GitHub repository to test this out quite easily. You should notice you're able to access the BrushCollection class inside the WindowsXamlHost_ChildChanged handler in the MainWindow.xaml.cs file without any issue, but attempting to access that class outside that handler causes the problem above.

I'd presume this is due to the ChildChanged event handler being called while on the same thread the WindowsXamlHost is using.

Again, this setup is limiting though as it means all the code I want to write has to be in code-behind in this event handler, rather than being able to set any of it via XAML. It feels counterintuitive and messy to me, and I feel concerned if the app will crash if I try to interact with any of these controls outside the context of the ChildChanged event handler.

marb2000 commented 3 years ago

Thanks @JaykeBird for opening the bug and for informing us back with the workaround.