Re: Enumerating in separate threads--pointless because the thread is blocked? (.NET 2.0)
- From: "Homer J. Simpson" <root@xxxxxxxxx>
- Date: Wed, 13 Feb 2008 15:12:25 -0500
Nobody after a week, huh?
If someone thinks he might have an answer, but I need to elaborate on
something, please let me know. Right now I've all but abandoned the idea of
giving the user a Cancel button and make him wait for the operation to
complete...
"Homer J. Simpson" <root@xxxxxxxxx> wrote in message
news:uESgVaQaIHA.5768@xxxxxxxxxxxxxxxxxxxxxxx
I'm probably not doing things like I'm "supposed' to, because I'm not
getting the results I'm expecting...
Sorry for the long post, but please bear with me...I have to elaborate on
what I'm trying to do what I've done trying to get there.
I'm retrieving all the details for the cimv2\Win32_Product class (others
too, but this is the one class I'm testing against). I'm not using a
'where' clause to narrow down the results--that's besides the point. As
others have probably already observed, this can be quite slow. Upwards of
a minute on my system, probably more. I thought I'd alleviate the problem
by having a thread retrieve data in the background, so my UI remains
responsive and the user has a Cancel button to abort the data retrieval
process.
My .NET pseudo-code is as follows:
ManagementObjectSearcher mos = new ManagementObjectSearcher(
...query... );
ManagementObjectCollection moc = mos.Get();
foreach( ManagementBaseObject mbo in moc ) {
ProcessThisRecord( mbo );
}
However, my observation has been that as soon as I single-step (in the
debugger) over mos.Get(), an instance of wmiprvse.exe pins the CPU, and
then as I enter the foreach loop, whatever thread is executing the loop
then blocks, and the debugger waits for wmiprvse.exe to finish fetching
all the data (a minute on my system for this particular class) before
it'll return on the next line of code. Obviously my UI won't even repaint
while it's busy.
I tried doing this in a separate thread. The UI remains responsive, and
my Cancel button's callback is triggered correctly. All it does is set a
bool flag (bCancelPending) that's a member of my form class. The idea was
to have:
foreach( ... )
if( bCancelPending == true )
break;
ProcessThisRecord( mbo );
}
However, the thread is blocked as soon as I enter the foreach loop. After
a minute, execution resumes, the Cancel flag is checked, and it breaks out
of the loop, as desired...however, I still had to wait for all the records
to be fetched before the code checked for the flag...duh. Once I'm past
that initially delay, ripping through the loop takes no time at all.
I thought instead of using a foreach loop, I'd use something like:
lock( moc.SyncRoot ) {
ManagementObjectCollection.ManagementObjectEnumerator e =
moc.GetEnumerator();
while( e.MoveNext() ) {
ManagementBaseObject mbo = e.Current;
ProcessThisRecord( mbo );
}
}
Much to my surprise, even with this, as I single-step through the code,
e.MoveNext() also blocks while all the data is fetched...after the
one-minute pause, the loop then resumes and again manages to rips through
the data in no time at all...so once again, there's no point in trying to
set a flag to verify within the loop.
In other words, unless I'm doing something very wrong, there's no point in
even trying to spawn different threads to do work in the background.
Then I stumbled upon ManagementOperationObserver--neat...it definitely
seems like the preferred way to get data from WMI asynchronously, without
the hassle of setting up my own threading.
I hooked it all up, managed to get the callbacks triggered...only, this is
even slower than looping. Other classes, like Win32_Processor, which only
returns 2 records on my dual-core system, and is nearly instantaneous
using a loop, takes 45-60 seconds using this callback technique. I'm not
sure, based on my Google search results, whether further investigation in
that area is warranted, because it seems like there's a lot of complaints
that this callback technique is slow. If it's *expected* to be as slow as
I'm seeing, then there's no point in me spending more time here.
Now...I suspect I'm gonna have to post some actual code before I can get
concrete answers...fact is, I've made such a mess of my code right now
after so much trial and error that I've just had to revert back to my
original version, which makes no attempt at threading or asynchronous
operations. What I'm really looking for is a simple, *working* sample that
asynchronously fetches data from a class, fills some control (listview or
anything else) with this data, and lets the user click a Cancel button to
abort fetches that take a long time (and preferably then fills some
control with the data that has been retrieved up to this point). Bonus
points for something that can later resume where it left off, but I'll be
a happy camper if I can get this far.
.
- References:
- Enumerating in separate threads--pointless because the thread is blocked? (.NET 2.0)
- From: Homer J. Simpson
- Enumerating in separate threads--pointless because the thread is blocked? (.NET 2.0)
- Prev by Date: Re: WMI Associators - Vista - SCSI Disk Enum
- Next by Date: Max number of WMI connections
- Previous by thread: Enumerating in separate threads--pointless because the thread is blocked? (.NET 2.0)
- Next by thread: Disk I/O by process and file
- Index(es):
Relevant Pages
|