当前位置: 移动技术网 > IT编程>开发语言>c# > winform开发使用通用多线程基类分享(以队列形式)

winform开发使用通用多线程基类分享(以队列形式)

2019年07月18日  | 移动技术网IT编程  | 我要评论

 

复制代码 代码如下:

/// <summary>
    /// 队列多线程,t 代表处理的单个类型~
    /// </summary>
    /// <typeparam name="t"></typeparam>
    public abstract class queuethreadbase<t>
    {
        #region 变量&属性
        /// <summary>
        /// 待处理结果
        /// </summary>
        private class pendingresult
        {
            /// <summary>
            /// 待处理值
            /// </summary>
            public t pendingvalue { get; set; }
            /// <summary>
            /// 是否有值
            /// </summary>
            public bool ishad { get; set; }
        }
        /// <summary>
        /// 线程数
        /// </summary>
        public int threadcount
        {
            get { return this.m_threadcount; }
            set { this.m_threadcount = value; }
        }
        private int m_threadcount = 5;
        /// <summary>
        /// 取消=true
        /// </summary>
        public bool cancel { get; set; }
        /// <summary>
        /// 线程列表
        /// </summary>
        list<thread> m_threadlist;
        /// <summary>
        /// 完成队列个数
        /// </summary>
        private volatile int m_completedcount = 0;
        /// <summary>
        /// 队列总数
        /// </summary>
        private int m_queuecount = 0;
        /// <summary>
        /// 全部完成锁
        /// </summary>
        private object m_allcompletedlock = new object();
        /// <summary>
        /// 完成的线程数
        /// </summary>
        private int m_competedcount = 0;
        /// <summary>
        /// 队列锁
        /// </summary>
        private object m_pendingqueuelock = new object();
        private queue<t> m_innerqueue;
        #endregion


        #region 事件相关
        /// <summary>
        /// 全部完成事件
        /// </summary>
        public event action<competedeventargs> allcompleted;
        /// <summary>
        /// 单个完成事件
        /// </summary>
        public event action<t, competedeventargs> onecompleted;
        /// <summary>
        /// 引发全部完成事件
        /// </summary>
        /// <param name="args"></param>
        private void onallcompleted(competedeventargs args)
        {
            if (allcompleted != null)
            {
                try
                {
                    allcompleted(args);//全部完成事件
                }
                catch { }
            }
        }
        /// <summary>
        /// 引发单个完成事件
        /// </summary>
        /// <param name="pendingvalue"></param>
        /// <param name="args"></param>
        private void ononecompleted(t pendingvalue, competedeventargs args)
        {
            if (onecompleted != null)
            {
                try
                {
                    onecompleted(pendingvalue, args);
                }
                catch { }

            }
        }
        #endregion

        #region 构造
        public queuethreadbase(ienumerable<t> collection)
        {
            m_innerqueue = new queue<t>(collection);
            this.m_queuecount = m_innerqueue.count;
        }

        #endregion

        #region 主体
        /// <summary>
        /// 初始化线程
        /// </summary>
        private void initthread()
        {
            m_threadlist = new list<thread>();
            for (int i = 0; i < threadcount; i++)
            {
                thread t = new thread(new threadstart(innerdowork));
        m_threadlist.add(t);
                t.isbackground = true;
                t.start();
            }
        }
        /// <summary>
        /// 开始
        /// </summary>
        public void start()
        {
            initthread();
        }
        /// <summary>
        /// 线程工作
        /// </summary>
        private void innerdowork()
        {
            try
            {
                exception doworkex = null;
                doworkresult doworkresult = doworkresult.continuethread;
                var t = currentpendingqueue;
                while (!this.cancel && t.ishad)
                {
                    try
                    {
                        doworkresult = dowork(t.pendingvalue);
                    }
                    catch (exception ex)
                    {
                        doworkex = ex;
                    }
                    m_completedcount++;
                    int precent = m_completedcount * 100 / m_queuecount;
                    ononecompleted(t.pendingvalue, new competedeventargs() { competedprecent = precent, innerexception = doworkex });
                    if (doworkresult == doworkresult.abortallthread)
                    {
                        this.cancel = true;
                        break;
                    }
                    else if (doworkresult == doworkresult.abortcurrentthread)
                    {
                        break;
                    }
                    t = currentpendingqueue;
                }

                lock (m_allcompletedlock)
                {
                    m_competedcount++;
                    if (m_competedcount == m_threadlist.count)
                    {
                        onallcompleted(new competedeventargs() { competedprecent = 100 });
                    }
                }

            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// 子类重写
        /// </summary>
        /// <param name="pendingvalue"></param>
        /// <returns></returns>
        protected virtual doworkresult dowork(t pendingvalue)
        {
            return doworkresult.continuethread;
        }
        /// <summary>
        /// 获取当前结果
        /// </summary>
        private pendingresult currentpendingqueue
        {
            get
            {
                lock (m_pendingqueuelock)
                {
                    pendingresult t = new pendingresult();
                    if (m_innerqueue.count != 0)
                    {
                        t.pendingvalue = m_innerqueue.dequeue();
                        t.ishad = true;
                    }
                    else
                    {
                        t.pendingvalue = default(t);
                        t.ishad = false;
                    }
                    return t;
                }
            }
        }

        #endregion

        #region 相关类&枚举
        /// <summary>
        /// dowork结果枚举
        /// </summary>
        public enum doworkresult
        {
            /// <summary>
            /// 继续运行,默认
            /// </summary>
            continuethread = 0,
            /// <summary>
            /// 终止当前线程
            /// </summary>
            abortcurrentthread = 1,
            /// <summary>
            /// 终止全部线程
            /// </summary>
            abortallthread = 2
        }
        /// <summary>
        /// 完成事件数据
        /// </summary>
        public class competedeventargs : eventargs
        {
            public competedeventargs()
            {

            }
            /// <summary>
            /// 完成百分率
            /// </summary>
            public int competedprecent { get; set; }
            /// <summary>
            /// 异常信息
            /// </summary>
            public exception innerexception { get; set; }
        }
        #endregion

    }

1.从构造函数来看,处理的是一个确定的列表.没错.这个多线程只能处理已经确定的列表,你是否会问.可不可以一边添加,一边处理呢?(呵呵,可以,请联系楼主,当然你也可以自己写,是吧?!)

复制代码 代码如下:

public queuethreadbase(ienumerable<t> collection)

2.提供撤销的功能

复制代码 代码如下:

/// <summary>
        /// 取消=true
        /// </summary>
        public bool cancel { get; set; }

3.提供线程个数修改功能

复制代码 代码如下:

/// <summary>
        /// 线程数
        /// </summary>
        public int threadcount
        {
            get { return this.m_threadcount; }
            set { this.m_threadcount = value; }
        }

4.提供多种事件响应,如单个完成,全部完成的事件

复制代码 代码如下:

/// <summary>
        /// 全部完成事件
        /// </summary>
        public event action<competedeventargs> allcompleted;
        /// <summary>
        /// 单个完成事件
        /// </summary>
        public event action<t, competedeventargs> onecompleted;

5.提供完成的百分率

复制代码 代码如下:

/// <summary>
        /// 完成事件数据
        /// </summary>
        public class competedeventargs : eventargs
        {
            public competedeventargs()
            {

            }
            /// <summary>
            /// 完成百分率
            /// </summary>
            public int competedprecent { get; set; }
            /// <summary>
            /// 异常信息
            /// </summary>
            public exception innerexception { get; set; }
        }

6.提供终止线程的方式,继续/单线程终止/全部终止

复制代码 代码如下:

/// <summary>
        /// dowork结果枚举
        /// </summary>
        public enum doworkresult
        {
            /// <summary>
            /// 继续运行,默认
            /// </summary>
            continuethread = 0,
            /// <summary>
            /// 终止当前线程
            /// </summary>
            abortcurrentthread = 1,
            /// <summary>
            /// 终止全部线程
            /// </summary>
            abortallthread = 2
        }

你是否会问?怎么用呢?别急....请看

复制代码 代码如下:

/// <summary>
    /// 下载线程对了.
    /// </summary>
    public class downloadqueuethread:queuethreadbase<int>
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="list">下载的列表id</param>
        public downloadqueuethread(ienumerable<int> list):base(list)
        {

        }
        /// <summary>
        /// 每次多线程都到这里来,处理多线程
        /// </summary>
        /// <param name="pendingvalue"列表id></param>
        /// <returns></returns>
        protected override doworkresult dowork(int pendingid)
        {
            try
            {

                //..........多线程处理....
                return doworkresult.continuethread;//没有异常让线程继续跑..

            }
            catch (exception)
            {

                return doworkresult.abortcurrentthread;//有异常,可以终止当前线程.当然.也可以继续,
                //return  doworkresult.abortallthread; //特殊情况下 ,有异常终止所有的线程...
            }

            //return base.dowork(pendingvalue);
        }
    }

用法

总结:

多线程在什么时候都会用到.不用到是你不会用.多线程要一定的编程基础,如果你觉得有点难度,那你可以学习并且借鉴人家已有的东西.少走弯路,是我们程序员经历嗷嗷待哺后的心声.本文以交流态度和感恩心态,贡献给有需要的人们.

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网