RPC_E_CANTCALLOUT_ININPUTSYNCCALL when trying to access USB device

2

I have this piece of code:

var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DiskDrive");              
foreach (var queryObj in searcher.Get().Cast<ManagementObject>()) //Error points to this line

Basically what this code does is, it runs through a list of connected devices and looks if the one i want is connected. If I run this code while the device is already connected at the time when the code is ran, then it works flawlessly. But if I trigger this code with DBT_DEVICEARRIVAL (which is event the system sends when some device is connected and i catch it with

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if(..DBT_DEVICEARRIVAL..) 
        new ScanDevices(); /*Here lies the code from above (in the class)*/
}

I get this error:

An outgoing call cannot be made since the application is dispatching an input-synchronous call. (Exception from HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)).

If I put thread.sleep(5000) on top of the code above, so it waits 5 seconds before executing, then the code works. So the conflict must be somewhere, where other things try to access that device first and hog it all for themselves.

I searched the internet and found suggestions like sending custom postmessage to myself to trigger the code, but I have little idea on how to do that, or even how would that solved the problem.

What is the best solution here?

c#
windows
exception
asked on Stack Overflow May 4, 2014 by user3595338 • edited Jun 4, 2018 by Rob K

1 Answer

5

Wrap your code in a new thread:

Thread thread = new Thread(() =>
{
    ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
    foreach (ManagementObject currentObject in theSearcher.Get())
    {
        Debug.WriteLine("Device present: " + currentObject);          
        ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
        serial = theSerialNumberObjectQuery["SerialNumber"].ToString();
    }
});
thread.Start();
thread.Join(); //wait for the thread to finish
answered on Stack Overflow Apr 10, 2015 by mvermand

User contributions licensed under CC BY-SA 3.0