microsoft / WindowsAppSDK

The Windows App SDK empowers all Windows desktop apps with modern Windows UI, APIs, and platform features, including back-compat support, shipped via NuGet.
https://docs.microsoft.com/windows/apps/windows-app-sdk/
MIT License
3.84k stars 320 forks source link

Wrong thread error when using GraphicsCapturePicker #1443

Open bryankeller opened 3 years ago

bryankeller commented 3 years ago

Whenever I call PickSingleItemAsync on a GraphicsCapturePicker, I get a runtime error:

System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'

I'm using Visual Studio 2019, WinUI 1.8, and I'm running Windows 10 10.0.19042. Here's my code - a simple button (defined in my XAML) is what's calling StartCapture.

        public MainWindow()
        {
            this.InitializeComponent();

            startSessionButton.Visibility = GraphicsCaptureSession.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
        }

        private void startSession_Click(object sender, RoutedEventArgs e)
        {
            StartCapture();
        }

        private async void StartCapture()
        {
            var picker = new GraphicsCapturePicker();
            var item = await picker.PickSingleItemAsync();
            if (item != null)
            {
                Console.WriteLine(item.ToString());
            }
            else
            {
                Console.WriteLine("Failed to get an item");
            }
        }
jonwis commented 3 years ago

If this isn't from inside a UWP, maybe check out https://github.com/dotnet/core/issues/5670 ? The capture picker needs to know which window to parent against when displaying its own experience.

(@AdamBraden FYI)

bryankeller commented 3 years ago

Thanks @jonwis - pretty new to windows dev so appreciate the tip. I did come across that thread, but I'm not sure if doing the workaround from that thread you linked to works in project reunion

https://github.com/dotnet/core/issues/5670#issuecomment-737903026

Maybe I'm missing an import, not sure which though.

jonwis commented 3 years ago

Hey @rkarman / @AdamBraden / @angelazhangmsft - here's a place we could use some more samples and helpers. Check out what this sample does and what this C#/WinRT sample does.

  1. Get the IWindowNative from your Window type
  2. Use it to get the WindowHandle (the underlying HWND) as an IntPtr
  3. Get the IInitializeWithWindow from your GraphicsCaptureSession and call Initialize with the IntPtr on it
  4. Call the rest of the Capture APIs.

(And yes, the use of the window interop helper type on WinUI3 types from WinAppSDK should work just fine, and we'll get a sample written to show it.)

angelazhangmsft commented 3 years ago

@bryankeller, We recently added helpers in C#/.NET for the classes that require IInitializeWithWindow to associate the object with a window handle in desktop apps. There is documentation on the C# helpers here. In your scenario, you should be able to use this code:

var picker = new Windows.Graphics.Capture.GraphicsCapturePicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
var item = await picker.PickSingleItemAsync();
...
manodasanW commented 3 years ago

@bryankeller Another thing to call out given you are seeing a wrong thread error is, I would make sure you are on a recent version of the .NET 5 SDK as we did have some fixes a couple months ago in the Windows SDK projection for that error.

angelazhangmsft commented 2 years ago

@bryankeller - are you still running into this issue?