locked
Might be a bug of PnpObject.FindAllAsync API

    Question

  • Hi,

    I try to use bellow code to get the "Manufacturer" "ItemNameDisplay" and "ModelName" of end-user's device.

    But the problem is that in some device, this API will block the whole application for the second call and then crash.

    string[] properties = { "System.Devices.Manufacturer", "System.ItemNameDisplay", "System.Devices.ModelName" };
    var containers = await PnpObject.FindAllAsync(PnpObjectType.DeviceContainer, properties);
    Sunday, November 18, 2012 5:46 AM

Answers

  • Thanks for the clarification.  This is not a bug.

    Task<TResult>.Result() waits until the async operation is complete before returning. As you can tell, this is not recommended in the UI thread because it will cause the app to freeze.

    http://msdn.microsoft.com/en-us/library/dd321468.aspx

    If you are trying to return the items in a wrapper function, you should call await instead of .Result().

    async void EnumerateDeviceContainers(...)

    {

       var list = await modelName();  // this will assign the result to list asynchronously.

       // put code that uses list here 

    }

     

     

     

     

    Thursday, November 22, 2012 2:57 AM

All replies

  • Hi Haibo,

    If you debug the crash in Visual Studio, what is the exception and stack? And with what device(s) do you see the crash?

    Regards,

    lisa


    Sunday, November 18, 2012 7:35 PM
  • Apology for my late reply and thanks a lot for kindly rely.

    Actually, I found it may be my fault of usage.

    I tracked it for a while, and found if I call this api as following way, it will throw a invalid exception:

    string[] properties = { "System.ItemNameDisplay", "System.Devices.ModelName", "System.Devices.Connected" };
    var containers = PnpObject.FindAllAsync(PnpObjectType.DeviceContainer, properties).GetResults();

    So could you help to figure out why that? thanks in advance!

    Br

    Wednesday, November 21, 2012 5:19 AM
  • Are you using the sample?

    http://code.msdn.microsoft.com/windowsapps/Device-Enumeration-Sample-a6e45169/sourcecode?fileId=44728&pathId=1979427360

    Here's the snippet of code showing the right usage (with await):

    string[] properties = { "System.ItemNameDisplay""System.Devices.ModelName""System.Devices.Connected" }; 
    var containers = await PnpObject.FindAllAsync(PnpObjectType.DeviceContainer, properties); 
     
    DeviceContainersOutputList.Items.Clear(); 
    rootPage.NotifyUser(containers.Count + " device container(s) found", NotifyType.StatusMessage); 
    foreach (PnpObject container in containers) 

        DeviceContainersOutputList.Items.Add(new DisplayItem(container)); 

    Wednesday, November 21, 2012 5:55 AM
  • Sure, I used this sample.

    Actually it mean it must run as a async Task.

    If wrapper the snippet as async func, and call it using Result for simple, it will cause another problem.  like this:

    async void EnumerateDeviceContainers(object sender, RoutedEventArgs eventArgs)
    {
        var list = modelName().Result; // this will freeze whole app
    }
    
    async Task<ICollection<DisplayItem>> modelName()
    {
        string[] properties = { "System.ItemNameDisplay", "System.Devices.ModelName", "System.Devices.Connected" };
        var containers = await PnpObject.FindAllAsync(PnpObjectType.DeviceContainer, properties);
    
        List<DisplayItem> items = new List<DisplayItem>();
    
        foreach (PnpObject container in containers)
        {
            items.Add(new DisplayItem(container));
        }
    
        return items;
    }

    It would be an special case, but it indeed will cause freeze.

    Wednesday, November 21, 2012 7:20 AM
  • Thanks for the clarification.  This is not a bug.

    Task<TResult>.Result() waits until the async operation is complete before returning. As you can tell, this is not recommended in the UI thread because it will cause the app to freeze.

    http://msdn.microsoft.com/en-us/library/dd321468.aspx

    If you are trying to return the items in a wrapper function, you should call await instead of .Result().

    async void EnumerateDeviceContainers(...)

    {

       var list = await modelName();  // this will assign the result to list asynchronously.

       // put code that uses list here 

    }

     

     

     

     

    Thursday, November 22, 2012 2:57 AM