Click here to Skip to main content
15,888,610 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys,

i just got a huge problem with a WMI query about the connected USB sticks. I use a predefined class USBStorageDriveManager that receives the connected USB sticks by the following WMI query:

C++
ManagementObjectCollection ^ drives = (gcnew ManagementObjectSearcher("SELECT Caption,DeviceID FROM Win32_DiskDrive WHERE InterfaceType='USB'"))->Get();


Now, i want to add a new panel, which has to be able to deal with USB Sticks. But when I call the USBStorageDriveManager::GetUSBStorageDrivesLetters() static function, my program breaks off with a DisconnectedContext-warning. Exactly in the line within the USBStorageDriveManagers where the WMI query is executed.
The same call, is easily used at two other locations in the main project. In contrast to my call, the other two calls are behind a Timer_Tick.

After a bunch of internet research i have read, that it might have something to do with recursive calls. The problem could be solved by an asynchronous call of the method which executes the WMI Get.

So if i create a new delegate and use it as follows:

C++
GetDrivesDelegate^ delGetDrives = gcnew GetDrivesDelegate(&USBStorageDriveManager::GetUSBStorageDrivesLetters);
IAsyncResult^ result = delGetDrives->BeginInvoke(nullptr, nullptr);
array < String^ > ^ aDrives = delGetDrives->EndInvoke(result);


instead of the direct call which i have used previously:

C++
array < String^ > ^ aDrives = USBStorageDriveManager::GetUSBStorageDrivesLetters();


it works quite well so far.

However, as soon as I meet my MessageBox ("Caution, USB stick is no longer available"), and the thread of my new panels gets blocked, it takes a moment and then comes the DisconnectedContext-warning again. Probably just the time until one of the timers is firing.

After some further research, i read the following hint: In a WMI query, the underlying COM object would be registered to the thread, which has executed the query. This registration would only be lifted when the thread is finished. But as long as this registration exists, no other thread can use a WMI query / the COM object.
Is that true? If so, is there any possibility to "unsubscribe" such a registration, even before the thread exits?

So this Begin-/EndInvoke can only be necessary/successful, because it runs on a different thread. (I use, as i said, the BeginInvoke method of the delegate, not the Invoke method of the my Control).
But thats what i dont understand, in the case in which the call of GetUSBStorageDrivesLetters gets executed on another thread, it should be irrelevant, whether the thread of my panel blocks at the moment of my message box or not.

Like i said, unlike my call, the other two calls are behind a Timer_Tick. But this shouldn't make a difference, because those timers are System::Windows::Forms::Timer's and they executing their tick-calls on the same thread as the Control runs.

I traced this with

C++
Thread::CurrentThread->GetHashCode();



and it seems to be true. The other two calls are running on one thread (no. 1), but mine runs (of course) on another thread. But why my program crashes when the thread of my new Panel gets blocked?

Sincerely,

Allgaeuer
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900