david-coder
2/10/2020 - 8:08 AM

TaskController

public class TaskController
{

    /// <summary>
    /// 创建任务控制器
    /// </summary>
    /// <param name="title">控制器名称(线程标识)</param>
    /// <param name="interval">时间控制间隔的长度(秒)</param>
    /// <param name="owner">与线程相关的控件</param>
    public TaskController(string title, int interval = 1, Control owner = null)
    {
        this.Owner = owner;
        this.Interval = interval;
        this.Title = title;
    }

    /// <summary>
    /// 控制器名称(线程标识)
    /// </summary>
    public string Title { get; }

    /// <summary>
    /// 时间控制间隔的长度(秒)
    /// </summary>
    public int Interval { get; }

    /// <summary>
    /// 与线程相关的控件
    /// </summary>
    public Control Owner { get; }

    private System.Threading.Thread thread;
    private int id = -1;
    private List<bool> active = new List<bool>();

    /// <summary>
    /// 指示控制器线程是否正在运行
    /// </summary>
    public bool IsRunning => thread?.IsAlive == true;

    private class Seed
    {
        public string Key { get; set; }
        public Action Task { get; set; }
        public int Span { get; set; }
    }
    private List<Seed> seeds = new List<Seed>();

    /// <summary>
    /// 向控制器中追加任务单元
    /// </summary>
    /// <param name="key">任务单元标识</param>
    /// <param name="task">执行任务时调用的方法</param>
    /// <param name="span">执行间隔(Interval的倍数)</param>
    public void SetSeed(string key, Action task, int span)
    {
        var seed = seeds.Find(s => s.Key == key);
        if (seed == null)
        {
            seeds.Add(new Seed
            {
                Key = key,
                Task = task,
                Span = span
            });
        }
        else
        {
            if (task != null) seed.Task = task;
            if (span > 0) seed.Span = span;
        }
    }

    /// <summary>
    /// 从控制器中移除任务单元
    /// </summary>
    /// <param name="key">任务单元标识</param>
    public void RemoveSeed(string key)
    {
        try
        {
            var seed = seeds.Find(s => s.Key == key);
            if (seed != null) seeds.Remove(seed);
        }
        catch (Exception) { }
    }

    /// <summary>
    /// 启动控制器线程
    /// </summary>
    public void Start()
    {

        id++;
        active.Add(true);

        thread = new System.Threading.Thread(thread_proc)
        {
            Name = Title + "#" + id,
            IsBackground = true
        };
        thread.Start(id);

    }

    /// <summary>
    /// 停止控制器线程
    /// </summary>
    public void Stop()
    {

        try
        {
            for (int i = 0; i < active.Count; i++)
            {
                active[i] = false;
            }
        }
        catch (Exception) { }

        try
        {
            thread?.Abort();
            thread = null;
        }
        catch (Exception) { }

    }

    private void thread_proc(object param)
    {

        int id = (int)param;
        long meters = 0;

        try
        {

            //启动后延时
            System.Threading.Thread.Sleep(2000);

            //首次执行(忽略间隔)
            seeds.OrderBy(s => s.Span).ToList().ForEach(s =>
            {
                if (s.Task != null)
                {
                    if (Owner != null) Owner.Invoke(s.Task);
                    else s.Task.Invoke();
                }
            });

        }
        catch (Exception) { }

        while (true)
        {
            try
            {

                //延时
                if (!active[id]) return;
                for (int i = 0; i < Interval; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    if (!active[id]) return;
                }

                //计数器
                meters++;

                //按间隔执行
                int count = 0;
                foreach (var s in seeds)
                {
                    if (s.Span > 0 && (meters % s.Span == 0))
                    {

                        count++;
                        if (count > 1) System.Threading.Thread.Sleep(1000);

                        if (s.Task != null)
                        {
                            if (Owner != null) Owner.Invoke(s.Task);
                            else s.Task.Invoke();
                        }

                    }
                }

            }
            catch (Exception ex)
            {
                OnError?.Invoke(ex);
            }
        }

    }

    /// <summary>
    /// 执行方法中发生异常时触发的事件
    /// </summary>
    public event Action<Exception> OnError;

}