Home > database >  How to loop through an IObservable containing an IEnumerable in C#?
How to loop through an IObservable containing an IEnumerable in C#?

Time:06-14

I am trying to get a list of paired bluetooth devices using C#, the method used returns an IObservable collection containing IEnumerable objects which contain Bluetooth Device objects. The compiler marks the variable assigned the return type of this method as IObservable<IEnumerable<IDevice>>. I am trying to access the IDevice from the collection. The documentation of the method suggests the use of a Subscribe() method to iterate through the collection but I do not know if this Subscribe() method needs some external trigger

List<string> devNames= new List<string>();
//I have tested the line below and it returns true so its not a permission issue
if (adapter.CanViewPairedDevices())
{
//here is my device collection variable
IObservable<IEnumerable<IDevice>> devices =adapter.GetConnectedDevices();
//here is how I try to get device names from the above collection
devices.Subscribe(deviceResult =>
       {
         foreach(var device in deviceResult){
                        devNames.Add(device.Name);
                                            }
       });
}
//devNames is still empty at this point

My list of names is empty at the end of the method call, does Subscribe need some kind of trigger ? Is there an alternative way of iterating through such a type that will result in names being added to the list?

CodePudding user response:

What you want is this:

IList<string> devNames =
    adapter
        .GetConnectedDevices()
        .SelectMany(devices => devices.Select(device => device.Name))
        .ToList()
        .Wait();

That will block on the observable which may not be desirable, so you can also await this code and make it asynchronous. Try this:

IList<string> devNames = await
    adapter
        .GetConnectedDevices()
        .SelectMany(devices => devices.Select(device => device.Name))
        .ToList();

You could use .Subscribe(...) but you wouldn't populate the List<string> devNames in the subscription. Using Rx, like I have above, you end up with an observable returns your IList<string>, so in the subscription you would need to know what you want to do with the list. You haven't said that in the question, so I can't answer that.

CodePudding user response:

devNames variable is not part of your code snippet but I assume it is declared somewhere prior to this snippet execution.

The nature of Subscriptions is that they are async.
devices.Subscribe executes syncronously but the code within the subscription:

foreach(var device in deviceResult)
{
    devNames.Add(device.Name);
}

will execute at a later point, meaning that synchronous code after devices.Subscribe might not be able to see the results.

You can add your logic that references devNames within the subscription as well to resolve this issue.

List<string> bNames= new List<string>();
//I have tested the line below and it returns true so its not a permission issue
if (adapter.CanViewPairedDevices())
{
    //here is my device collection variable
    var devices =adapter.GetConnectedDevices();
    //here is how I try to get device names from the above collection
    devices.Subscribe(deviceResult =>
    {
        foreach(var device in deviceResult)
        {
            devNames.Add(device.Name);
        }
        // devNames is available here
    });
}

CodePudding user response:

try this out please I think it will work with you

 devNames = observable.Select(t => t.Name).ToList();
  • Related