/// <summary>
        /// The callback for the asset cache when a texture has been retrieved.  This method queues the
        /// texture sender for processing.
        /// </summary>
        /// <param name="textureID"></param>
        /// <param name="texture"></param>
        public void TextureCallback(UUID textureID, AssetBase texture)
        {
            //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));

            // There may still be texture requests pending for a logged out client
            if (closed)
            {
                return;
            }

            lock (m_textureSenders)
            {
                TextureSender.TextureSender textureSender;
                if (m_textureSenders.TryGetValue(textureID, out textureSender))
                {
                    // XXX It may be perfectly valid for a texture to have no data...  but if we pass
                    // this on to the TextureSender it will blow up, so just discard for now.
                    // Needs investigation.
                    if (texture == null || texture.Data == null)
                    {
                        if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID))
                        {
                            missingTextureLimitStrategy.MonitorRequests(textureID);

                            //                            m_log.DebugFormat(
                            //                                "[TEXTURE]: Queueing first TextureNotFoundSender for {0}, client {1}",
                            //                                textureID, m_client.AgentId);
                        }

                        ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
                        EnqueueTextureSender(textureNotFoundSender);
                    }
                    else
                    {
                        if (!textureSender.ImageLoaded)
                        {
                            textureSender.TextureReceived(texture);
                            EnqueueTextureSender(textureSender);

                            foundTextureLimitStrategy.MonitorRequests(textureID);
                        }
                    }

                    //m_log.InfoFormat("[TEXTURE] Removing texture sender with uuid {0}", textureID);
                    m_textureSenders.Remove(textureID);
                    //m_log.InfoFormat("[TEXTURE] Current texture senders in dictionary: {0}", m_textureSenders.Count);
                }
                else
                {
                    m_log.WarnFormat(
                        "[TEXTURE]: Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
                        textureID);
                }
            }
        }
        /// <summary>
        /// The callback for the asset cache when a texture has been retrieved.  This method queues the
        /// texture sender for processing.
        /// </summary>
        /// <param name="textureID"></param>
        /// <param name="texture"></param>
        public void TextureCallback(UUID textureID, AssetBase texture)
        {
            //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));

            // There may still be texture requests pending for a logged out client
            if (closed)
                return;

            lock (m_textureSenders)
            {
                TextureSender.TextureSender textureSender;
                if (m_textureSenders.TryGetValue(textureID, out textureSender))
                {
                    // XXX It may be perfectly valid for a texture to have no data...  but if we pass
                    // this on to the TextureSender it will blow up, so just discard for now.
                    // Needs investigation.
                    if (texture == null || texture.Data == null)
                    {
                        if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID))
                        {
                            missingTextureLimitStrategy.MonitorRequests(textureID);

                            //                            m_log.DebugFormat(
                            //                                "[TEXTURE]: Queueing first TextureNotFoundSender for {0}, client {1}",
                            //                                textureID, m_client.AgentId);
                        }

                        ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
                        EnqueueTextureSender(textureNotFoundSender);
                    }
                    else
                    {
                        if (!textureSender.ImageLoaded)
                        {
                            textureSender.TextureReceived(texture);
                            EnqueueTextureSender(textureSender);

                            foundTextureLimitStrategy.MonitorRequests(textureID);
                        }
                    }

                    //m_log.InfoFormat("[TEXTURE] Removing texture sender with uuid {0}", textureID);
                    m_textureSenders.Remove(textureID);
                    //m_log.InfoFormat("[TEXTURE] Current texture senders in dictionary: {0}", m_textureSenders.Count);
                }
                else
                {
                    m_log.WarnFormat(
                        "[TEXTURE]: Got a texture uuid {0} with no sender object to handle it, this shouldn't happen",
                        textureID);
                }
            }
        }