question

LucaFranceschini-7892 avatar image
0 Votes"
LucaFranceschini-7892 asked ·

Camera is not always correctly detected

Sometimes (this is not always reproducible) the following call gives me an empty list, failing to detect a USB connected camera:

 await MediaFrameSourceGroup.FindAllAsync().AsTask().ConfigureAwait(false);

The camera is correctly connected though, since other applications are able to use it. Disconnecting and reconnecting the camera seems to fix it, but this happens quite often. The following code however successfully detects the camera (but I need a source group for video capture purposes):

 await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture).AsTask().ConfigureAwait(false);

The issue appeared on more than one computer.

Is there anything I should consider when retrieving a camera this way? Is there a more robust way to do this?

I followed this guide to process frames: https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/process-media-frames-with-mediaframereader

windows-wpf
· 3
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello @LucaFranceschini-7892 , when you try to use the camera, please make sure that the related API calls are in the UI thread, so when you use MediaFrameSourceGroup.FindAllAsync(), you don’t need to add ConfigureAwait(false). You can try to simply use await and make sure No other apps are using the camera.

0 Votes 0 ·

I'm using this API from a synchronous WPF application, so at some point I have to block on async calls. If I don't use ConfigureAwait(false) to preserve the context, and call from the main UI thread (which is unique), won't I deadlock?

0 Votes 0 ·

Hello, if your question is related to WPF development, please mark the wpf tag, and the relevant engineer will analyze your question from the perspective of WPF

1 Vote 1 ·

1 Answer

DaisyTian-MSFT avatar image
0 Votes"
DaisyTian-MSFT answered ·

When you call the method from the UI, deadlock is generally not caused by this. The ConfigureAwait method isn’t special, it’s not recognized in any special way by the compiler or by the runtime. It is simply a method that returns a struct (a ConfiguredTaskAwaitable) that wraps the original task it was called on as well as the specified Boolean value. When you use ConfigureAwait(false) , even if there is a current context or scheduler to call back to, it pretends as if there isn’t. So I think it's no need for you to use ConfigureAwait(false). For more details about ConfigureAwait , please refer to the Stephen's blog ConfigureAwait FAQ

By the way, I tested below code in my .Net core 5.0 project ,and both of them can detect the camera without disconnecting and reconnecting the camera.

  var frameSourceGroups0 = await MediaFrameSourceGroup.FindAllAsync().AsTask().ConfigureAwait(false);
  var frameSourceGroups1 = await MediaFrameSourceGroup.FindAllAsync();

If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 4 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I'm using this API from a WPF application that is generaly synchronous (which is a fairly common situation I think, especially with legacy code). So this is essentially what I have:

 void SomeWpfMethod() {
     // This happens on the main WPF UI thread
     InitializeCameraAsync().GetAwaiter().GetResult();
 }

 void async Task InitializeCameraAsync() {
     var groups = await MediaFrameSourceGroup.FindAllAsync();
     // more stuff
 }

If I just do like the code above, it deadlocks. My understanding is that the main UI thread is waiting for the result in SomeWpfMethod, and when MediaFrameSourceGroup.FindAllAsync completes, it tries to resume execution on the captured context, which is the main UI thread that is waiting, hence the deadlock. This is why I was using ConfigureAwait(false).

Am I getting this all wrong?


0 Votes 0 ·

@LucaFranceschini-7892 In my view, you don't need to use GetAwaiter().GetResult(), it can deadlock when it's used in a one-thread-at-a-time context. You can use async/await to implement what you want. I edited your code as below:

   async void SomeWpfMethod()
         {
             // This happens on the main WPF UI thread
             await InitializeCameraAsync();
         }
          static async Task InitializeCameraAsync()
         {
             var groups = await MediaFrameSourceGroup.FindAllAsync();
             // more stuff
         }
0 Votes 0 ·

In an ideal scenario I would agree with you, but I'm working on a huge codebase that does not use async, and without GetAwaiter().GetResult() a considerable part of the application would need to be made async, all the way up to the main thread, which is just not viable.

This is also what Microsoft seems to suggest when gradually introducing asynchronous code to a synchronous codebase, it is described here as "the blocking hack" https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development

Thanks for your reply, I'll see if I can make sure the API is called from the main UI thread, and see if that helps.

0 Votes 0 ·
Show more comments