After running TexturePipeline in my app I find that many threads (40+) are waiting in ImagePackageHandler and RefreshDownloadsTimer_Elapsed. This seems to be more than the 10 downloads I asked for. Looking at the code, TexturePipeline.ImagePacketHandler locks _Transfers and then does all of it's work (callbacks and all) with the lock in force. TexturePipeline.RefreshDownloadsTimer_Elapsed locks _Tranfers, does a lot of work and can even call TexturePipeline.RequestImage who again locks _Transfers to do all of its work.
Not sure if this is how it's supposed to work but it seems that the locking covers too much and causes threads to deadlock. I will check more later.
What is are your settings for MAX_CONCURRENT_TEXTURE_DOWNLOADS?
Another thought that comes to mind is the download workers are using the system threadpool (same as the inbound packet handlers) So although 40+ textures seems to be too much, 40+ threads waiting is not unreasonable at all. So are you sure all 40 of these are locked in the pipeline?
We'll be switching over to ReaderWriterLockSlim at some point which will give us finer grained control of the pipeline locks.
I did some pretty extensive testing and I found having more than 4 or so concurrent requests did not increase the speed of retrieving textures but definitely caused more timeouts. This is course may need to be different depending on other factors as well.
This turned out to be my bad – I was mapping wrong parameters and requesting more than 100 texture request slots and, since the max number of threads in the pool was 100, that stopped up my whole application.