Exemple #1
0
        // ----------------------------------------------------------------
        #region // Private Methods

        /// <summary>
        /// オペレーションの追加
        /// </summary>
        /// <param name="addOperation">追加するオペレーション</param>
        static void AddOperation(IProcessOperation addOperation)
        {
            if (_processOperationsQueue == null)
            {
                _processOperationsQueue   = new Queue <IProcessOperation>();
                _runningProcessOperations = new List <IProcessOperation>();
                EditorApplication.update  = () =>
                {
                    if (_runningProcessOperations.Count < EditorAsyncProcess.ProcessLimit &&
                        _processOperationsQueue.Count > 0)
                    {
                        _runningProcessOperations.Add(_processOperationsQueue.Dequeue());
                    }
                    for (int i = 0; i < _runningProcessOperations.Count; ++i)
                    {
                        var operation = _runningProcessOperations[i];
                        if (!operation.Update())
                        {
                            _runningProcessOperations.RemoveAt(i);
                        }
                    }
                };
            }
            _processOperationsQueue.Enqueue(addOperation);
        }
        /// <summary>
        /// <see cref="IProcessOperation"/> オブジェクトを登録する。
        /// </summary>
        /// <param name="processOperation">
        /// <see cref="IProcessOperation"/> オブジェクト。
        /// </param>
        /// <returns>登録できたならば true 。既に登録済みならば false 。</returns>
        public bool Add(IProcessOperation processOperation)
        {
            ArgumentValidation.IsNotNull(processOperation, nameof(processOperation));

            lock (this.OperationTaskLock)
            {
                if (this.Operations.Contains(processOperation))
                {
                    return(false);
                }

                // 追加
                this.Operations.Add(processOperation);

                // タスク数が少ないなら追加
                while (
                    this.Tasks.Count < this.TaskCountLimit &&
                    this.Tasks.Count < this.Operations.Count)
                {
                    if (!this.PushTask())
                    {
                        break;
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// <see cref="IProcessOperation.Update"/>
        /// メソッド呼び出しで送出された直近の例外を取得する。
        /// </summary>
        /// <param name="processOperation">
        /// <see cref="IProcessOperation"/> オブジェクト。
        /// </param>
        /// <returns>例外。登録されていないか例外が送出されていないならば null 。</returns>
        public Exception GetLastException(IProcessOperation processOperation)
        {
            ArgumentValidation.IsNotNull(processOperation, nameof(processOperation));

            lock (((ICollection)this.LastExceptionMap).SyncRoot)
            {
                return
                    (this.LastExceptionMap.TryGetValue(processOperation, out var ex) ?
                     ex : null);
            }
        }
        /// <summary>
        /// <see cref="IProcessOperation"/> オブジェクトの登録を破棄する。
        /// </summary>
        /// <param name="processOperation">
        /// <see cref="IProcessOperation"/> オブジェクト。
        /// </param>
        /// <returns>破棄できたならば true 。登録されていないならば false 。</returns>
        public bool Remove(IProcessOperation processOperation)
        {
            ArgumentValidation.IsNotNull(processOperation, nameof(processOperation));

            List <Task> removedTasks = null;

            lock (this.OperationTaskLock)
            {
                // 位置検索
                var index = this.Operations.IndexOf(processOperation);
                if (index < 0)
                {
                    return(false);
                }

                // 削除
                this.Operations.RemoveAt(index);

                // 次回処理対象インデックスより手前を削除したなら補正
                if (this.OperationIndex > index)
                {
                    --this.OperationIndex;
                }

                // タスク数が多すぎるなら終わらせる
                if (this.Tasks.Count > this.Operations.Count)
                {
                    removedTasks = new List <Task>();
                    while (this.Tasks.Count > this.Operations.Count)
                    {
                        var task = this.PopTask();
                        if (task == null)
                        {
                            break;
                        }
                        removedTasks.Add(task);
                    }
                }
            }
            lock (((ICollection)this.LastExceptionMap).SyncRoot)
            {
                this.LastExceptionMap.Remove(processOperation);
            }

            // lock 内で Wait するとデッドロックするので注意
            if (removedTasks != null && removedTasks.Count > 0)
            {
                Task.WaitAll(removedTasks.ToArray());
            }

            return(true);
        }