locked
GetCharacteristicsAsync() sometimes fails with HRESULT: 0x80070020 RRS feed

  • Question

  • Hello,

    I wrote a windows service in C# that's permanently listening for BLE devices offering a certain service-UUID. Once it detects such a device it tries to read the characteristics of the service and exchange some date with the peripheral. Unfortunately the API does not seem to be the most stable as I get the above mentioned error on calling GetCharacteristicsAsync() on the service.

    It looks like I do not close a handle properly but I just cannot see where this happens. 

     void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
                BluetoothLEAdvertisementReceivedEventArgs eventArgs)
        {
          BluetoothLEDevice device = null;
          try
          {
            device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
            if (device == null)
            {
              Log.Debug("Returning cause no device was found...");
              return;
            }
    
            var availableServicesResult = await device.GetGattServicesAsync();
            if (availableServicesResult.Status != GattCommunicationStatus.Success)
            {
              Log.Debug("Failed to read services (Status: {availableServicesResult.Status})");
              device.Dispose();
              return;
            }
    		
    		myService = availableServicesResult.Services.SingleOrDefault(
                    s => s.Uuid == new Guid("<my-very-own-UUID>"));
    		if (myService == null)
    		{
    			throw new ApplicationException("Failed to read service");
    		}
    
    		// This is where the exception occurs after some time the service runs:
    		GattCharacteristicsResult characteristicResult =
    			await myService.GetCharacteristicsAsync();
           
          }
          catch (Exception ex)
          {
            Log.Error(ex, "Could not handle advertisment correctly!");
          }
          finally
          {
            device?.Dispose();
          }
        }

    After banging my head against this error for several days I thought that perhaps somebody here can see what I just cannot detect or can verify that it's indeed a misfunction and has a possible solution to work artound this issue.




    • Moved by Hart Wang Monday, October 9, 2017 6:11 AM
    • Moved by Breeze Liu Monday, October 9, 2017 8:57 AM c#
    • Edited by Frank Ertl Tuesday, October 10, 2017 3:21 PM another typo
    Friday, October 6, 2017 1:05 PM

All replies

  • Maybe some of the functions only work inside the threads having the corresponding threading model that was set by Thread.SetApartmentState, or only work inside sections marked with lock statement because parallelism is not supported.

    Monday, October 9, 2017 5:25 AM
  • Hi,

    Thank you for posting MSDN forum.

    According to the error code, it looks like the current process cannot access the file because it is being used by another process, which cause the issue.

    Could you please provide more version information about Bluetooth device and test device information? 

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Hart Wang Tuesday, October 10, 2017 9:57 AM
    Monday, October 9, 2017 6:08 AM
  • Thanks for the hint that parallelism is not supported. 

    I have set the threading model to STA in the main-method of the service. Setting a lock around the call is not possible as locks are not allowed for async calls. 

    Looking at my logfiles I do not see where a concurrent access from my service is happening, perhaps some other process tries to read the characteristics at the same time. Or I am handling this completely wrong. How can I solve this issue?

    Tuesday, October 10, 2017 3:17 PM
  • Hello Hart

    I am working with a Acer TravelMate P259-G running Windows 10, Insider Build. The devices I am trying to access are a Samsung Galaxy S6, a Galaxy S7, a Fairphone 2, a few iOS devices. The error happens undeterminately on all of them from time to time.

    Regards,

    Frank

    Tuesday, October 10, 2017 3:20 PM
  • Hi,

    Thank you for your feedback.

    Did you build the current program at windows Insider?

    If yes, I suggest that you can post your feedback on windows Insider website.

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, October 11, 2017 7:15 AM
  • Hi Hart

    yes, I build it on windows insider, but the problem occurs also on a normal windows 10 installation when I install and  run my service there, so I think it is independent of the insider preview. Any clues what's going wrong?

    Regards,

    Frank

    Wednesday, October 11, 2017 7:25 AM
  • Hi Frank,

    What's the information of the exception?

    You implemented both Client & Server and Watcher & Publisher in your application. Have you tried to use only one pattern?(Not very sure that's the cause, I will reply again if I have more helpful information)

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Monday, October 16, 2017 9:28 AM
  • Hi Charles

    I only implemented Client (Watcher). The server (Publisher) is an Android device.

    Unfortunately there is no more information on the exception, the complete message from the log is:

    "Problem handling advertisement: Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird. (Exception from HRESULT: 0x80070020)    bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       bei Apiida.BLENative.GATT.GattClient.<HandleAdvertisementAsync>d__26.MoveNext()

    "

    Regards,

    Frank

    Monday, October 23, 2017 5:33 AM
  • Hi Frank,

    What I replied before means that your windows device is working as a watcher and at the same time it wants to work as a client to connect to the server(publisher at the same time). 

    I suggest that try to make your windows device work as watcher or as client but not at the same time.

    You can refer this link to know difference between Client & Server and Watcher & Publisher.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Wednesday, October 25, 2017 9:31 AM
  • Hi Charles,

    I've already read through the link you gave, but I just don't get it where I am going wrong.

    How can I achieve what I want to achieve (Getting advertisements and then connecting to the device and read data and so on)? 

    Most of the examples I found do it in a similar way that I do.

    Regards,

    Frank

    Wednesday, October 25, 2017 10:08 AM
  • Hi Frank,

    Your client get advertisements frequently and each time it tries to connect to server(your android device). I think frequent connections is redundant.

    I have consulted some one who is more experienced in BluetoothLE development and we have similar idea.

    We recommend that you use GATT Client(windows device) to read data from and write data to GATT Server(android device). Use DeviceWatcher instead of BluetoothLEAdvertisementWatcher to discover your server and then connect to it.

    This link will help you to write your client code.

    Hope this is helpful to you.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Thursday, October 26, 2017 8:07 AM
  • Hi Charles

    thank you for the ongoing help. I tried to use a DeviceWatcher like in the link you gave.

    The Added-Handler has the following code:

    var device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
    Log.Info($"Opened Device {device.DeviceId}");
    var availableServices = await device.GetGattServicesAsync();
    if (availableServices.Status != GattCommunicationStatus.Success)
    {
       Log.Warn($"Failed to read services (Status: {availableServices.Status})");
       return;
    }

    Unfortunately this yields the same result, very often I get "Status: Unreachable" (Sometimes even on the first try).

    Perhaps this has something to do with the fact that I am writing a service not an UWP-app?

    Regards,

    Frank
    Thursday, October 26, 2017 12:49 PM
  • Hi Frank,

    I wonder if other Bluetooth devices in your surroundings discovered and connected by your client but cannot be reached caused this problem. And what you said about "non UWP-app" may be the cause too.

    So my suggestion is that:

    1. List all devices discovered by your client, pick up the device that you want to connect and make it's name condition when you try to connect. Below is an example:

    if(deviceInfo.Name!="Your Device Name")return;
    var device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
    Log.Info($"Opened Device {device.DeviceId}");
    var availableServices = await device.GetGattServicesAsync();
    if (availableServices.Status != GattCommunicationStatus.Success)
    {
       Log.Warn($"Failed to read services (Status: {availableServices.Status})");
       return;
    }

    2. If previous solution doesn't work, try use UWP BluetoothLE sample to check if your device can be reached.

    What's more, you can tell us information of your android device. What is it specifically? You can also paste your code here to show us how you implement BluetoothLE client.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thursday, October 26, 2017 1:25 PM
  • Hi Charles

    this works partially. The devicename for iPhones always defaults to "iPhone" and for Android devices it is always empty as I cannot advertise service UUID and devicename at the same time (this would exceed the maximum advertisement length). At the moment we work around this by changing the last few bytes of the service-UUID to something that's unique for a device and handle the advertisement in a way that a connection is only established if this unique device UUID is not already connected. So we avoid frequent connections using an advertisment watcher. Still after some time the services become unreachable and only a restart of the bluetooth device in the windows PC (the client) is able to change this. Is there a possibility to track this down, that means getting more information why the services become unreachable (to many open handles, failed memory allocation or something like this) for example by changing the logging level for the bt-driver?

    Regards,

    Frank

    Friday, October 27, 2017 5:36 AM
  • Hi Frank,

    The maximum advertisement length can be 31 bytes and UUID is 128 bits long, so why you "cannot advertise service UUID and devicename at the same time"? What's more, can you advertise "iPhone" with UUID at the same time?

    Have you tried UWP BluetoothLE sample?

    What is your android device? A band? A watch? or something else?

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, October 27, 2017 6:17 AM
  • Hi Charles,

    sorry for the late reply, I've been out of house a few days. The device I use is a Smartphone (e.g. Samsung S6, S7, Sony Xperia). When advertising the devicename together with the service UUID I get "

    ADVERTISE_FAILED_DATA_TOO_LARGE

    " inside the android code. As per default the devicename on all the devices of a manufacturer seems to be equal this is not a unique identifier, too. 

    I have tried the UWP example before writing my service. But I did not run it long enough to produce this error. It only happens after the service is up and running for sometime, whereat "sometimes" differs. Could be a few minutes or a few hours. Seems to depend on the count of advertisments and other BLE operations.

    So my main question remains:

    How can I find out more about the reason for this error?

    Regards,

    Frank

    PS: One mor hinte: When the status "Unreachable" occurs and I stop my service, turn off bluetooth via settings turn it on again and start my service everything works fine for a while. Without toggling the BT it does not. So I think there is something filling up behind the scenes.


    • Edited by Frank Ertl Thursday, November 2, 2017 3:27 PM Added more information
    Thursday, November 2, 2017 11:44 AM
  • Hi Frank,

    Frankly, your reply makes me confused. So let me go through me questions:

    1. You have tried UWP sample, does it reproduce your scenario? Does it work fine?

    2. Your device is smartphone, so low energy is built in feature of your device? Or you use some simulation app? Or you write codes yourself?

    3. What's your central device? Laptop with windows 10?

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, November 3, 2017 6:05 AM
  • Hi Charles

    1. Our scenario is a little bit different from the UWP sample, but the essential parts are the same. I did not let it run long enough to reproduce the issue as I just wanted to see if the architecture I developed for the whole system will work as expected, but will try it once again. I got a new laptop so I have to download and build the sample once more and try to reproduce the error.

    2. BLE is build in all of the smartphones I use for testing and the code to access the BLE stack on the smartphone was written by myself.

    3. Central device is a laptop running windows 10 (1709, 16299.19)

    Regards,

    Frank

    Friday, November 3, 2017 7:17 AM
  • Hi Frank,

    I recommend you try UWP sample again. If it works, change your code according to that sample. If not, you can paste your device watch and connect code here that we can discuss about.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, November 3, 2017 8:08 AM
  • Hi Charles

    I have the sample once more up and running. Now I think I know what the main difference (and possibly the cause for my problems) is: In the sample you add DeviceInformation-objects to a list and after a user interaction (select and button click) the connection is established from this information. 

    Unfortunately that's not possible for our scenario. The scenario is that multiple devices advertise a custom service. The central (our windows service) should then write a unique ID to one of this service's characteristics  (one device after the other). Finally if one device decides that the central should be the one to talk to it sends a new advertisement containing the unique id and the central should then register to be notified when the characteristics change.

    This must run without user interaction. So it might be a solution to use a DeviceWatcher and then connect to the devices, but I cannot figure out at which point I should read the services. The EnumerationComplete-handler I wrote is not invoked for some reason and in the updatehandler I get the same errors as before.

    Regards,

    Frank

    Tuesday, November 7, 2017 3:11 PM
  • Hi Frank,

    This must run without user interaction. So it might be a solution to use a DeviceWatcher and then connect to the devices, but I cannot figure out at which point I should read the services. The EnumerationComplete-handler I wrote is not invoked for some reason and in the updatehandler I get the same errors as before.

    If you can enumerate devices in UWP sample, it should be no problem to enumerate without user interaction. So make sure you succeed enumerating all devices you want to connect with in UWP sample. Then compare you codes with UWP sample to see the difference. What's more, I think it impossible to get error with updatehandler in your application while no error in the sample. So would you please check them all and give me the feedback?

    Thanks a lot,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Wednesday, November 8, 2017 2:28 AM
  • Hi Charles

    Enumeration is not the problem, this works without any errors. The errors appear when I connect to the devices. As the EnumerationCompleted-event is not received I tried to do the connect in the updatehandler and then I get the errors.

    When is the EnumerationCompleted-event triggered? Perhaps I am missing something that I don't see. I assume that the errors would go away when I connect after the enumeration is done. 

    Regards,

    Frank

    Wednesday, November 8, 2017 6:28 AM
  • Hi Frank,

    EnumerationCompleted should be triggered when all devices are discovered. But I think enumeration not complete should not prevent devices from being connected. 

    First, EnumerationCompleted not triggered is wired, so try turn all your devices' bluetooth off except one to see whether EnumerationCompleted will be triggered.

    Second, I don't think errors would go away when you connect after the enumeration is done. What error did you get when you tried to connect in the updatehandler?

    Third, both central and peripheral codes are written by yourself. Keep just one side self written codes to judge what's the cause. My suggestion is, use UWP sample to connect your devices, if it doesn't work, there is high probability that your self written codes go wrong on your android devices.

    Waiting for your feedback.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Wednesday, November 8, 2017 7:12 AM
  • Hi Charles

    trying out your suggestions, I noticed something weird with the sample. After discovering some of the test devices I tried to connect one of them and read the services. The call to GetGattServicesAsync() results in status "Unreachable". As I followed the documentation for creating a peripheral and adding services on android this is really annoying as another central I have written for Windows 7 using a HCI-interface to a TI dongle works well with my Android code.

    However, the weird thing I noticed is: One of my devices does not get detected, even when I can see that it advertises (using a BLE sniffer), and another device I turned off in the meantime still gets enumerated (even after a restart of the UWP sample). Is this how the sample should work? Also after some time (a few seconds) the devices enumerated vanish from the list, so it's difficult to select one to connect to.

    So I have two questions:

    1. Why is the status "Unreachable" when trying to read the services (using HCI with dongle it works!)?
    2. Why is an advertising device (proven by BLE sniffer) not enumerated?

    Regards,

    Frank

    Wednesday, November 8, 2017 8:47 AM
  • Hi Frank,

    I also reproduced weird thing you encountered with UWP samples on my laptop and BLE simulator on my android phone. My phone still got enumerated even after bluetooth turned off. I think that's how UWP BLE works, it may store BLE device information somewhere.

    I think your 2 questions are related with how UWP BLE works, i.e. how UWP BLE enumerates devices and connects with them.

    You should have noticed this thread. Our engineer has asked help from other resources, they will update when possible.

    Sorry about not help you fix your problem.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.




    Thursday, November 9, 2017 2:44 AM
  • Hi Charles

    thank you for that information. The thread you mentioned is known to me, I participated there. :-)

    So I think we have to be patient till this is fixed.

    Nevertheless, thank you very much for your patience and ongoing help!

    Best Regards,

    Frank

    Thursday, November 9, 2017 6:32 AM
  • Hi Frank,

    Thanks for your comprehension and cooperation!

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thursday, November 9, 2017 6:35 AM
  • I have the same problem.
    Tried connecting to a TI SensorTag and get the same error message.
    My code is based on the BLE Explorer sample app but put in Windows Forms.
    The Explorer app seems to work fine but I constantly get this FileLoadException with my app
    Thursday, November 9, 2017 10:44 AM
  • Has this issue been resolved? I'm having a similar problem:

    Running VS2017 15.5.4 on Windows 10 Fall Creators trying to access BLE devices in a WPF (not UWP).
    There is an exception thrown upon call to GattDeviceService function GetCharacteristicsAsync. This occurs if the service discovery is performed more than once per application run. Maybe the connection or service is not properly disposing?

    Typical exception is:
    System.IO.FileLoadException
      HResult=0x80070020
      Message=The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)
      Source=mscorlib
      StackTrace:
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at CharacteristicsError.MainWindow.<OnAdvertisementReceived>d__5.MoveNext() in C:\projects\CharacteristicsError\CharacteristicsError\MainWindow.xaml.cs:line 77

    Tuesday, January 30, 2018 8:25 PM
  • I had the same problem sometimes and disposing the service after disposing the device helped in my case.

    So in your case changing your code to

    device?.Dispose();
    myService?.Dispose();

    should help.

    However I don't think it's a good idea to connect to a device each time you receive an advertisement.

    Monday, April 9, 2018 9:36 AM