Ejemplo n.º 1
0
        /// <summary>执行命令</summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="func">回调函数</param>
        /// <param name="write">是否写入操作</param>
        /// <returns></returns>
        public virtual TResult Execute <TResult>(Func <RedisClient, TResult> func, Boolean write = false)
        {
            // 写入或完全管道模式时,才处理管道操作
            if (write || FullPipeline)
            {
                // 管道模式直接执行
                var rds = _client.Value;
                if (rds == null && AutoPipeline > 0)
                {
                    rds = StartPipeline();
                }
                if (rds != null)
                {
                    var rs = func(rds);

                    // 命令数足够,自动提交
                    if (AutoPipeline > 0 && rds.PipelineCommands >= AutoPipeline)
                    {
                        StopPipeline();
                        StartPipeline();
                    }

                    return(rs);
                }
            }

            // 统计性能
            var sw = Counter?.StartCount();

            var i = 0;

            do
            {
                // 每次重试都需要重新从池里借出连接
                var client = Pool.Get();
                try
                {
                    client.Reset();
                    var rs = func(client);

                    Counter?.StopCount(sw);

                    return(rs);
                }
                catch (InvalidDataException)
                {
                    if (i++ >= Retry)
                    {
                        throw;
                    }
                }
                finally
                {
                    Pool.Put(client);
                }
            } while (true);
        }
Ejemplo n.º 2
0
        /// <summary>执行命令</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public virtual T Execute <T>(Func <RedisClient, T> func)
        {
            var client = Pool.Get();

            try
            {
                var i = 0;
                do
                {
                    try
                    {
                        var rs = func(client);
                        //// 如果返回Packet,需要在离开对象池之前拷贝,否则可能出现冲突
                        //if ((Object)rs is Packet pk) return (T)(Object)pk.Clone();

                        return(rs);
                    }
                    catch (InvalidDataException)
                    {
                        if (i++ >= Retry)
                        {
                            throw;
                        }
                    }
                } while (true);
            }
            finally
            {
                Pool.Put(client);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 2017-8-4
        /// Lets the pool manager know to recycle the item. The appropriate pool is notified and the object
        /// is reset and deactivated.
        ///
        /// WARNING: if the item was renamed, this will probably fail (depending on whether GetInstanceID()
        ///     uses the object name to generate the hashcode. When an item's hashcode cannot be found in
        ///     the pool, the item is destroyed and the return value is false.
        /// </summary>
        public static bool Put(GameObject item)
        {
            bool result = false;

            foreach (var p in pools)
            {
                IPool pool = p.Value;
                result = pool.Put(item);
                if (result)
                {
                    break;
                }
            }

            if (!result)
            {
                if (Application.isEditor)
                {
                    MonoBehaviour.DestroyImmediate(item);
                }
                else
                {
                    MonoBehaviour.Destroy(item);
                }
            }

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>访问地址获取字符串</summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static async Task <String> GetStringAsync(String address)
        {
            var client = Pool.Get();

            try
            {
                return(await client.DownloadStringAsync(address));
            }
            finally
            {
                Pool.Put(client);
            }
        }
Ejemplo n.º 5
0
        /// <summary>执行命令</summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="key">命令key,用于选择集群节点</param>
        /// <param name="func">回调函数</param>
        /// <param name="write">是否写入操作</param>
        /// <returns></returns>
        public virtual TResult Execute <TResult>(String key, Func <RedisClient, TResult> func, Boolean write = false)
        {
            using var span = Tracer?.NewSpan($"redis:{(write ? "write" : "read")}");
            if (span != null)
            {
                span.Tag = key;
            }

            // 写入或完全管道模式时,才处理管道操作
            if (write || FullPipeline)
            {
                // 管道模式直接执行
                var rds = _client.Value;
                if (rds == null && AutoPipeline > 0)
                {
                    rds = StartPipeline();
                }
                if (rds != null)
                {
                    var rs = func(rds);

                    // 命令数足够,自动提交
                    if (AutoPipeline > 0 && rds.PipelineCommands >= AutoPipeline)
                    {
                        StopPipeline(true);
                        StartPipeline();
                    }

                    return(rs);
                }
            }

            // 读操作遇到未完成管道队列时,立马执行管道操作
            if (!write)
            {
                StopPipeline(true);
            }

            // 统计性能
            var sw = Counter?.StartCount();

            var i = 0;

            do
            {
                // 每次重试都需要重新从池里借出连接
                var client = Pool.Get();
                try
                {
                    client.Reset();
                    return(func(client));
                }
                catch (InvalidDataException)
                {
                    if (i++ >= Retry)
                    {
                        throw;
                    }
                }
                finally
                {
                    Pool.Put(client);

                    Counter?.StopCount(sw);
                }
            } while (true);
        }
Ejemplo n.º 6
0
        /// <summary>执行命令</summary>
        /// <typeparam name="TResult">返回类型</typeparam>
        /// <param name="key">命令key,用于选择集群节点</param>
        /// <param name="func">回调函数</param>
        /// <param name="write">是否写入操作</param>
        /// <returns></returns>
        public virtual TResult Execute <TResult>(String key, Func <RedisClient, TResult> func, Boolean write = false)
        {
            // 写入或完全管道模式时,才处理管道操作
            if (write || FullPipeline)
            {
                // 管道模式直接执行
                var rds = _client.Value;
                if (rds == null && AutoPipeline > 0)
                {
                    rds = StartPipeline();
                }
                if (rds != null)
                {
                    var rs = func(rds);

                    // 命令数足够,自动提交
                    if (AutoPipeline > 0 && rds.PipelineCommands >= AutoPipeline)
                    {
                        StopPipeline(true);
                        StartPipeline();
                    }

                    return(rs);
                }
            }

            // 读操作遇到未完成管道队列时,立马执行管道操作
            if (!write)
            {
                StopPipeline(true);
            }

            // 统计性能
            var sw = Counter?.StartCount();

            var i = 0;

            do
            {
                // 每次重试都需要重新从池里借出连接
                var client = Pool.Get();
                try
                {
                    client.Reset();
                    return(func(client));
                }
                catch (InvalidDataException)
                {
                    if (i++ >= Retry)
                    {
                        throw;
                    }

                    Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    if (ex is SocketException || ex is IOException)
                    {
                        // 销毁连接
                        client.TryDispose();

                        // 网络异常时,自动切换到其它节点
                        _idxServer++;
                        if (++i < _servers.Length)
                        {
                            Thread.Sleep(100);
                            continue;
                        }
                    }

                    throw;
                }
                finally
                {
                    Pool.Put(client);

                    Counter?.StopCount(sw);
                }
            } while (true);
        }
Ejemplo n.º 7
0
        /// <summary>Starts the loading, setting the current image to <see cref="_LoadingTexture"/>, if available. If the image is already in cache, and <paramref name="loadCachedIfAvailable"/>==true, will load that instead</summary>
        public void Load(string imageURL, bool loadCachedIfAvailable = true, LoadCompleteDelegate onCompleted = null, Action onCanceled = null)
        {
            bool currentRequestedURLAlreadyLoaded = _CurrentRequestedURL == imageURL;

            _CurrentRequestedURL = imageURL;

            if (loadCachedIfAvailable)
            {
                bool foundCached = false;
                // Don't re-request if the url is the same. This is useful if there's no pool provided
                if (currentRequestedURLAlreadyLoaded)
                {
                    foundCached = _Texture != null;
                }
                else if (_Pool != null)
                {
                    Texture2D cachedInPool = _Pool.Get(imageURL) as Texture2D;
                    if (cachedInPool)
                    {
                        _Texture             = cachedInPool;
                        foundCached          = true;
                        _CurrentRequestedURL = imageURL;
                    }
                }

                if (foundCached)
                {
                    _RawImage.texture = _Texture;
                    if (onCompleted != null)
                    {
                        onCompleted(true, true);
                    }

                    return;
                }
            }

            _RawImage.texture = _LoadingTexture;
            var request = new SimpleImageDownloader.Request()
            {
                url    = imageURL,
                onDone = result =>
                {
                    if (!_DestroyPending && imageURL == _CurrentRequestedURL) // this will be false if a new request was done during downloading, case in which the result will be ignored
                    {
                        // Commented: not reusing textures to load data into them anymore, since in most cases we'll use a pool
                        //result.LoadTextureInto(_Texture);

                        if (_Pool == null)
                        {
                            // Non-pooled textures should be destroyed
                            if (_Texture)
                            {
                                DisposeTexture(_Texture);
                            }

                            _Texture = result.CreateTextureFromReceivedData();
                        }
                        else
                        {
                            var  textureAlreadyStoredMeanwhile = _Pool.Get(imageURL);
                            bool someoneStoredTheImageSooner   = textureAlreadyStoredMeanwhile != null;
                            if (someoneStoredTheImageSooner)
                            {
                                // Happens when the same URL is requested multiple times for the first time, and of course only the first
                                // downloaded image should be kept. In this case, someone else already have downloaded and cached the image, so we just discard the one we downloaded
                                _Texture = textureAlreadyStoredMeanwhile as Texture2D;
                            }
                            else
                            {
                                // First time downloaded => cache
                                _Texture = result.CreateTextureFromReceivedData();
                                _Pool.Put(imageURL, _Texture);
                            }
                        }

                        _RawImage.texture = _Texture;

                        if (onCompleted != null)
                        {
                            onCompleted(false, true);
                        }
                    }
                    else if (onCanceled != null)
                    {
                        onCanceled();
                    }
                },
                onError = () =>
                {
                    if (!_DestroyPending && imageURL == _CurrentRequestedURL)                     // this will be false if a new request was done during downloading, case in which the result will be ignored
                    {
                        _RawImage.texture = _ErrorTexture;

                        if (onCompleted != null)
                        {
                            onCompleted(false, false);
                        }
                    }
                    else if (onCanceled != null)
                    {
                        onCanceled();
                    }
                }
            };

            SimpleImageDownloader.Instance.Enqueue(request);
        }