Пример #1
0
 /// <summary>
 /// Выставить состояние процессора в "свободен" и выставить событие - "есть свободный процессор"
 /// </summary>
 /// <param name="poolItem"></param>
 public void FreeItem(LingvisticsProcessor poolItem)
 {
     lock ( _PoolItemList )
     {
         poolItem.Free();
         _FreeProcessorEvent.Set();
         Logger.DebugFormat("proc({0}) free => {1}", poolItem.ProcessID, GetStat());
     }
 }
Пример #2
0
 /// <summary>
 /// Закрытие лингв. процесса и удаление его из пула
 /// лингв. процесса должен предварительно залочен, например через вызов GetItem
 /// </summary>
 /// <param name="poolItem">Закрываемый объект</param>
 public void CloseItem(LingvisticsProcessor poolItem)
 {
     lock ( _PoolItemList )
     {
         _PoolItemList.Remove(poolItem);
         _FreeProcessorEvent.Set();
         Logger.InfoFormat("proc({0}) close => {1}", poolItem.ProcessID, GetStat());
     }
     poolItem.Close();
 }
Пример #3
0
        //возвращение свободного процессора
        public LingvisticsProcessor GetItem(ProcessingType procType)
        {
            int threadID = Thread.CurrentThread.ManagedThreadId;

            //возвратить сразу или добавить в очередь
            lock ( _PoolItemList )
            {
                if (_CloseState)
                {
                    throw (new ApplicationException("Сервер останавливается"));
                }

                Logger.DebugFormat("request for {0} fn", procType);

                //список свободных процессоров
                var freeItemList = _PoolItemList.Where(t => !t.Busy);

                //очереди пустые или процессоров больше 2 => вернуть процессор
                if (freeItemList.Count() > Math.Min(2, (_LightThreadQueue.Count + _HeavyThreadQueue.Count)))
                {
                    var poolItem = freeItemList.FirstOrDefault();
                    poolItem.Lock(procType);
                    //Если свободных процессоров нет, то сбросить событие
                    if (!freeItemList.Skip(1).Any())
                    {
                        _FreeProcessorEvent.Reset();
                    }
                    Logger.DebugFormat("proc({0}) lock w/o queue => {1}", poolItem.ProcessID, GetStat());
                    return(poolItem);
                }
                //Добавление в пул нового лингвистического процессора
                if (_PoolItemList.Count < _MaxInstanceInPool)
                {
                    var poolItem = new LingvisticsProcessor();
                    _PoolItemList.Add(poolItem);
                    //если очереди пустые => вернуть результат
                    if (_LightThreadQueue.Count == 0 && (procType == ProcessingType.Light || _HeavyThreadQueue.Count == 0))
                    {
                        poolItem.Lock(procType);
                        _FreeProcessorEvent.Reset();
                        Logger.DebugFormat("new proc({0}) lock => {1}", poolItem.ProcessID, GetStat());
                        return(poolItem);
                    }
                }
                //Добавить текущий поток в очередь
                if (procType == ProcessingType.Light)
                {
                    _LightThreadQueue.Enqueue(threadID);
                    Logger.DebugFormat("add to LightQueue => {0}", GetStat());
                }
                else //procType == ProcessingType.Heavy
                {
                    _HeavyThreadQueue.Enqueue(threadID);
                    Logger.DebugFormat("add to HeavyQueue => {0}", GetStat());
                }
                _ThreadStartDateTimeDictionary.Add(threadID, DateTime.Now);
            }

            var sw = Stopwatch.StartNew();

            //Цикл ожидания освобождения процессора
            for ( ; ;)
            {
                LingvisticsProcessor poolItem = null;
                //если сводных элементов нет, то переход в ожидание
                lock ( _PoolItemList )
                {
                    if (_CloseState)
                    {
                        throw (new ApplicationException("Сервер останавливается"));
                    }

                    //запросы типа Light, идут раньше чем запросы типа Heavy
                    if (procType == ProcessingType.Light || _LightThreadQueue.Count == 0)
                    {
                        //текущий поток соответствует первому элементу очереди
                        Queue <int> queue = (procType == ProcessingType.Light) ? _LightThreadQueue : _HeavyThreadQueue;
                        if (queue.Peek() == threadID)
                        {
                            poolItem = _PoolItemList.FirstOrDefault(t => !t.Busy);
                            //Добавление в пул нового лингвистического процессора
                            if (poolItem == null && _PoolItemList.Count < _MaxInstanceInPool)
                            {
                                poolItem = new LingvisticsProcessor();
                                _PoolItemList.Add(poolItem);
                            }
                            if (poolItem != null)
                            {
                                queue.Dequeue();
                                _ThreadStartDateTimeDictionary.Remove(threadID);
                                poolItem.Lock(procType);
                                //Если больше нет свободных процессоров, то сброс события ожидания
                                if (!_PoolItemList.Any(t => !t.Busy))
                                {
                                    _FreeProcessorEvent.Reset();
                                }
                                sw.Stop();
                                Logger.DebugFormat("proc({0}) lock (dT={1:F3}c) => {2}", poolItem.ProcessID, sw.Elapsed.TotalSeconds, GetStat());

                                return(poolItem);
                            }
                        }
                    }
                } //end lock

                //если свободных процессоров нет и событие сброшено, то ждать освобождения процессора по событию
                if (/*---ALWAYS TRUE--- poolItem == null &&*/ !_FreeProcessorEvent.WaitOne(0))
                {
                    Logger.Debug("WaitFor FreeProcEvent");
                    //При превышении таймаута => ошибка
                    var cur = DateTime.Now;
                    var end = _ThreadStartDateTimeDictionary[threadID].AddSeconds(Config.Default.ProcessorQueueTimeOutInSeconds);
                    if (cur > end || !_FreeProcessorEvent.WaitOne(end - cur))
                    {
                        //удалить поток из очереди
                        lock ( _PoolItemList )
                        {
                            if (_CloseState)
                            {
                                throw (new ApplicationException("Сервер останавливается"));
                            }

                            if (procType == ProcessingType.Light)
                            {
                                _LightThreadQueue = new Queue <int>(_LightThreadQueue.Where(t => t != threadID));
                            }
                            else
                            {
                                _HeavyThreadQueue = new Queue <int>(_HeavyThreadQueue.Where(t => t != threadID));
                            }
                            _ThreadStartDateTimeDictionary.Remove(threadID);
                        }
                        Logger.DebugFormat("present queue timeout: {0}", GetStat());
                        throw (new ApplicationException("Превышен таймаут на ожидание выполнения - недостаточно число процессов"));
                    }
                }
                //иначе короткая пауза для прохода остальных потоков
                else
                {
                    //время ожидания расчитывается из числа потоков
                    Logger.DebugFormat("SleepStart");
                    Thread.Sleep(1);
                    Logger.DebugFormat("SleepEnd");
                }
            }
        }