美文网首页
[个人框架 C_Framework] DelayExecute,

[个人框架 C_Framework] DelayExecute,

作者: hh5460 | 来源:发表于2018-11-05 15:22 被阅读0次

    开发过程中经常会遇到需要等待一段时间再执行某一个方法,或者循环执行某一个方法, 很多人第一时间想到的就是Invoke和InvokeRepeating,当然了,如果可以的话那么没有任何问题,而且推荐使用它们,但是有些情况可能不适合它们的使用条件,例如有ABCD 4个方法,它们是一个队列,A执行完B执行然后CD依次执行,中间等待各自的延迟,有人说,Invoke就可以啊,在A中InvokeB,在B中InvokeC...etc...我不是说这样不行,这样方法间的耦合太高且不优雅,而且假设A在执行过程中异常遇到错误中断,导致Invoke B 的代码段无法执行,那么后续就都无法执行了...
    那么我对以上几种需求,用协程做了封装,那么可以做到

    1.开启协程,延迟指定时间后执行一次,然后关闭协程,每个协程有自己的key标识
    2.开启协程,依次执行队列ABCDEFG,中间有各自的延迟等待...当队列执行时有新的项目加入,则加入到对列尾,如果全部执行完成,关闭队列
    3.开启协程,定时循环执行方法Func
    4.开启协程,传入系统委托Func<object,bool>,直到条件满足后,即Func的方法返回值为True,执行Action
    using UnityEngine;
    using System.Collections;
    using System;
    using System.Collections.Generic;
    
    public class DelayExecute : SingleFramework<DelayExecute>
    {
        public Dictionary<int, Coroutine> dicCoroutines = new Dictionary<int, Coroutine>();  //协程管理
    
        Queue<DelayItem> DelayQueues = new Queue<DelayItem>();       //延迟队列
    
        public static void EnQueue(System.Action action,float delayTime)
        {
            Instance._EnQueue (new DelayItem (action, delayTime));
        }
    
        void _EnQueue(DelayItem item)
        {
            DelayQueues.Enqueue(item);
        }
    
        public static void TodoOnceDelay(Action action, float delayTime)
        {
            Instance.TodoOnceDelay(new DelayItem(action, delayTime));
        }
    
        //延迟执行
        void TodoOnceDelay(DelayItem delayItem)
        {
            Coroutine coroutine = StartCoroutine(DelayToDo(delayItem));  //开始协程烤肉
            dicCoroutines.Add(delayItem.CoroutineKey, coroutine);        //加入字典管理
        }
    
        IEnumerator DelayToDo(DelayItem delayItem)
        {
            yield return new WaitForSeconds(delayItem.DelayTime);        //延迟等待
            delayItem.DelayAction();                                     //执行方法
            StopCoroutine(dicCoroutines[delayItem.CoroutineKey]);        //停止烤肉
            dicCoroutines.Remove(delayItem.CoroutineKey);                //字典中移除烤肉
        }
    
        //循环执行                       委托         延迟时间        循环时间          //循环次数
        public static void TodoCircle(Action action, float delayTime, float circleTime, int circleNum)
        {
            Instance._TodoCircle(action, delayTime, circleTime, circleNum);
        }
    
        Coroutine coroutineCircle;
        //循环执行                       委托         延迟时间        循环时间          //循环次数
        void _TodoCircle(Action action, float delayTime, float circleTime, int circleNum)
        {
            coroutineCircle = StartCoroutine(CircleTodo(action, delayTime, circleTime, circleNum));
        }
    
        //循环执行                       委托         延迟时间        循环时间      //循环次数   0表示无限循环
        IEnumerator CircleTodo(Action action, float delayTime, float circleTime, int circleNum)
        {
            yield return new WaitForSeconds(delayTime);
            WaitForSeconds wfs = new WaitForSeconds(circleTime);
            if (circleNum == 0)
            {
                while (true)
                {
                    if (action != null)
                    {
                        action();
                    }
                    yield return wfs;
                }
            }
            else
            {
                for (int i = 0; i < circleNum; i++)
                {
                    if (action != null)
                    {
                        action();
                    }
                    yield return wfs;
                }
            }
            StopCoroutine(coroutineCircle);
        }
    
    
        //静态方法方便调用
        public static void StartDelayQueues()
        {
            Instance._StartDelayQueues();
        }
    
        Coroutine coroutineDelayQueues;
        //开始执行延迟队列
        void _StartDelayQueues()
        {
            coroutineDelayQueues = StartCoroutine(DelayToDoQueues());
        }
    
        //关闭队列
        public void StopDelayQueues()
        {
            StopCoroutine(coroutineDelayQueues);
        }
    
        IEnumerator DelayToDoQueues()
        {
            while (DelayQueues.Count != 0)
            {
                DelayItem delayItem = DelayQueues.Dequeue();
                yield return new WaitForSeconds(delayItem.DelayTime);        //延迟等待
                delayItem.DelayAction();                                     //执行方法
            }
            StopDelayQueues();
        }
    
    
        Coroutine coroutineDelayUntil;
        /// <summary>
        /// 延迟等待,直到条件满足退出
        /// </summary>
        /// <param name="func"></param>
        /// <param name="parameter"></param>
        /// <param name="actionWaitOver"></param>
        public void DelayUntil(Func<object, bool> func, object parameter, Action actionWaitOver)
        {
            coroutineDelayUntil = StartCoroutine(Delay_Until(func, parameter, actionWaitOver));
        }
    
        IEnumerator Delay_Until(Func<object, bool> func, object parameter, Action actionWaitOver)
        {
            yield return new WaitUntil(() =>
            {
                return func(parameter);
            });
            if (actionWaitOver != null)
            {
                actionWaitOver();
            }
            StopCoroutine(coroutineDelayUntil);
        }
    
        protected class DelayItem
        {
            public Action DelayAction;   //延迟执行委托
            public float DelayTime;   //延迟时间    
            public int CoroutineKey;      //作为键存入字典中,当延迟执行完毕后根据键获取当前当前协程消除
    
            static int IncrementKey = 0;     //静态自增量,不遇确保唯一
    
            public DelayItem(Action action, float time)
            {
                this.DelayAction = action;
                this.DelayTime = time;
                this.CoroutineKey = IncrementKey++;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:[个人框架 C_Framework] DelayExecute,

          本文链接:https://www.haomeiwen.com/subject/qpesxqtx.html