C#实现线程管理类

在开发winform时候为了体验好,一般可以把长时间任务用线程执行。但是大多数情况是有多个费事操作需要执行。如果每个都开启线程的话。那么多个线程之间又是乱序执行的。很多业务需要按先后顺序执行。但又需要不卡UI。为此我在14年时候开发了线程管理类,用来管理线程执行。

源码

管理类基于BackgroundWorker类和队列实现。BackgroundWorker想了解的自己查文档。

实现如下:

///作者:张联珠
///日期:2014-03-01
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;

namespace Util
{
    #region 异步工具调用前初始化的委托
    /// <summary>
    /// 初始化异步工具的委托
    /// </summary>
    /// <param name="backGroundWorker">BackgroundWorker</param>
    public delegate void InitAsyUtil(BackgroundWorker backGroundWorker);
    #endregion

    #region 单线程时的后台执行者
    ///<summary  NoteObject="Class">
    /// [功能描述:内部的后台工作对象,如果要使后台有序,几个工具类都把任务交给该对象] <para/>
    /// [创建者:张联珠] <para/>
    /// [创建时间:2014年4月11日] <para/>
    ///<说明>
    ///  [说明:修改原工具类
    ///  使用说明:后台操作方法不要访问UI资源]<para/>
    ///</说明>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///</summary>
    public static class InnerBackGroundWorker
    {
        /// <summary>
        /// 私有的静态工作对象
        /// </summary>
        private static BackgroundWorker SelfBackgroundWorker = new BackgroundWorker();

        /// <summary>
        /// 后台队列
        /// </summary>
        private static Queue<object[]> WaiteQueue = new Queue<object[]>();

        /// <summary>
        /// 调用锁
        /// </summary>
        public static object Lock = new object();

        /// <summary>
        /// 运行一个任务,如果线程正忙,任务进入等待
        /// </summary>
        /// <param name="objs"></param>
        public static void RunWorkerAsync(object [] objs)
        {
           lock (WaiteQueue)
           {
            //如果后台正忙,进入队列等待
            if (SelfBackgroundWorker.IsBusy || WaiteQueue.Count > 0)
            {
                    WaiteQueue.Enqueue(objs);
            }
            else
            {
                InitAsyUtil initAsyUitil = objs[4] as InitAsyUtil;
                SelfBackgroundWorker = new BackgroundWorker();
                initAsyUitil(SelfBackgroundWorker);
                SelfBackgroundWorker.RunWorkerAsync(objs);
            }
           }
        }

        /// <summary>
        /// 运行任务结束时执行,如果队列没有等待的任务,什么也不做,否则执行下一条任务
        /// </summary>
        /// <param name="objs"></param>
        public static void RunWorkerAsync()
        {
            lock (WaiteQueue)
            {
                //如果队列中有等待
                if (!SelfBackgroundWorker.IsBusy && WaiteQueue.Count > 0)
                {
                    object[] objs = null;
                    objs = WaiteQueue.Dequeue();
                    SelfBackgroundWorker = new BackgroundWorker();
                    InitAsyUtil initAsyUitil = objs[4] as InitAsyUtil;
                    initAsyUitil(SelfBackgroundWorker);
                    SelfBackgroundWorker.RunWorkerAsync(objs);
                }
            }
        }
    }
    #endregion

    #region 带返回类型的异步工具
    ///<summary  NoteObject="Class">
    /// [功能描述:管理的异步工具类] <para/>
    /// [创建者:张联珠] <para/>
    /// [创建时间:2014年4月11日] <para/>
    ///<说明>
    ///  [说明:修改原工具类
    ///  使用说明:后台操作方法不要访问UI资源]<para/>
    ///</说明>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///</summary>
    public static class ManagedAsyncUtils<TResult>
    {
        /// <summary>
        /// 私有的静态工作对象
        /// </summary>
        private static BackgroundWorker SelfBackgroundWorker = null;


        /// <summary>
        /// 使用前出师化异步工具
        /// </summary>
        private static void InitUtil(BackgroundWorker backGroundWorker)
        {
            SelfBackgroundWorker = backGroundWorker;
            SelfBackgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            SelfBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
        }


        /// <summary>
        /// 异步调用
        /// </summary>
        /// <param name="invokeCompleted">回调方法委托()回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="businessObject">调用目标对象实例(后台方法所在类的对象)</param>
        /// <param name="methodName">后台执行的方法名称(要申明成公有,应为内部通过反射来访问,不是公有的话会访问不到。该操作方法不要访问UI资源,在回调方法里访问)</param>
        /// <param name="args">后台执行方法需要的参数(和参数顺序一样的object数组)</param>
        /// <param name="isSelfAsy">是否单独一个异步</param>
        public static void Invoke(Action<TResult, Exception> invokeCompleted, object businessObject,
            string methodName, object[] args,bool isSelfAsy=false)
        {
            if (!isSelfAsy)
            {
                lock (InnerBackGroundWorker.Lock)
                {
                    InnerBackGroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), isSelfAsy });
                }
            }
            else
            {
                InitUtil(new BackgroundWorker());
                SelfBackgroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), isSelfAsy });
            }
        }

        /// <summary>
        /// BackgroundWorker的后台方法
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">参数</param>
        private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //获得参数数组
            var arguments = e.Argument as object[];
            //获得回调方法
            var completeMethod = arguments[0];
            //获得业务实体
            var businessObject = arguments[1];
            //获得方法名
            var methodName = arguments[2] as string;
            //获得参数
            var args = arguments[3] as object[];
            //存放结果
            object result = null;
            //存放异常
            Exception ex = null;
            try
            {
                //参数类型集合
                List<Type> lstArgType = new List<Type>();
                //把所有参数的类型填入集合
                if (args != null && args.Length > 0)
                {
                    for (int i = 0; i < args.Length; i++)
                    {
                        lstArgType.Add(args[i].GetType());
                    }
                }
                //获得方法
                var method = GetTarMethod(businessObject.GetType(), methodName, lstArgType.ToArray());
                //如果没找到该方法,直接执行该业务实体的方法
                if (method == null)
                {
                    //执行,并把结果赋给结果对象
                    result = businessObject.GetType().GetMethod(methodName, lstArgType.ToArray()).Invoke(businessObject, args);
                }
                //如果找到了方法,则通过接口调方法
                else
                {
                    result = method.Invoke(businessObject, args);
                }
            }
            catch (Exception exThread)
            {
                ex = exThread;
            }
            //结果由参数带回
            e.Result = new object[] { result, completeMethod, ex, arguments[5] };
        }   

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var results = e.Result as object[];
            //取出结果
            var result = results[0];
            Exception ex = null;
            //如果结果带出的异常不为空
            if (results[2] != null)
            {
                var exThread = results[2] as Exception;
                //如果内部异常不为空,则取内部异常
                if (exThread.InnerException != null)
                {
                    ex = exThread.InnerException;
                }
                //否则直接取总异常
                else
                {
                    ex = exThread;
                }
            }
            try
            {
                //取出回调委托
                Action<TResult, Exception> method = results[1] as Action<TResult, Exception>;
                //如果返回结果为空,传该类型的默认值
                if (result == null)
                {
                    method(default(TResult), ex);
                }
                //否则传带出的结果
                else
                {
                    method((TResult)result, ex);
                }
            }
            //应对回调时回调对象已被销毁
            catch (Exception exc)
            {
                //把除了访问已释放的资源异常吃掉外,其他异常抛出,方便调试
                if (!(exc is ObjectDisposedException))
                {
                    throw exc;
                }
            }
            finally
            {
                //及时清除引用,防止以后错误调用的干扰
                SelfBackgroundWorker = null;
                if(!((bool)results[3]))
                {
                InnerBackGroundWorker.RunWorkerAsync();
                }
            }
        }

        /// <summary>
        /// 获得目标方法
        /// </summary>
        /// <param name="svcType">方法所在类型</param>
        /// <param name="methodName">方法名</param>
        /// <param name="argTypes">参数类型集合</param>
        /// <returns>方法信息</returns>
        private static MethodInfo GetTarMethod(Type svcType, string methodName, Type[] argTypes)
        {
            //获取由当前实体所实现的接口集合
            foreach (var item in svcType.GetInterfaces())
            {
                //通过名称和类型找方法
                var method = item.GetMethod(methodName, argTypes);
                //找到方法就返回
                if (method != null)
                {
                    return method;
                }
            }
            return null;
        }

    }
    #endregion

    #region 不带返回类型的异步工具
    ///<summary  NoteObject="Class">
    /// [功能描述:管理的异步工具类] <para/>
    /// [创建者:张联珠] <para/>
    /// [创建时间:2014年4月11日] <para/>
    ///<说明>
    ///  [说明:修改原工具类
    ///  使用说明:后台操作方法不要访问UI资源]<para/>
    ///</说明>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///</summary>
    public static class ManagedAsyncUtils
    {
        /// <summary>
        /// 私有的静态工作对象
        /// </summary>
        private static BackgroundWorker SelfBackgroundWorker = null;


        /// <summary>
        /// 使用前初始化异步工具
        /// </summary>
        public static void InitUtil(BackgroundWorker backGroundWorker)
        {
            SelfBackgroundWorker = backGroundWorker;
            SelfBackgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            SelfBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
        }

        /// <summary>
        /// 异步调用
        /// </summary>
        /// <param name="invokeCompleted">回调方法委托()回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="businessObject">调用目标对象实例(后台方法所在类的对象)</param>
        /// <param name="methodName">后台执行的方法名称(要申明成公有,应为内部通过反射来访问,不是公有的话会访问不到。该操作方法不要访问UI资源,在回调方法里访问)</param>
        /// <param name="args">后台执行方法需要的参数(和参数顺序一样的object数组)</param>
        /// <param name="isSelfAsy">是否单独一个异步</param>
        public static void Invoke(Action<Exception> invokeCompleted, object businessObject,
            string methodName,object[] args,bool isSelfAsy=false)
        {
            if (!isSelfAsy)
            {
                lock (InnerBackGroundWorker.Lock)
                {
                    InnerBackGroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), isSelfAsy });
                }
            }
            else
            {
                InitUtil(new BackgroundWorker());
                SelfBackgroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), isSelfAsy });
            }
        }

        /// <summary>
        /// 后台工作方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //提出方法参数
            var arguments = e.Argument as object[];
            //提出回调委托
            var completeMethod = arguments[0];
            //提出调用方法的对象
            var businessObject = arguments[1];
            //提出调用方法的名称
            var methodName = arguments[2] as string;
            //提出调用方法的参数
            var args = arguments[3] as object[];
            //异常
            Exception ex = null;
            try
            {
                //存所有的参数类型
                List<Type> lstArgType = new List<Type>();
                if (args != null && args.Length > 0)
                {
                    for (int i = 0; i < args.Length; i++)
                    {
                        lstArgType.Add(args[i].GetType());
                    }
                }
                //获得调用方法
                var method = GetTarMethod(businessObject.GetType(), methodName, lstArgType.ToArray());
                if (method == null)
                {
                    businessObject.GetType().GetMethod(methodName, lstArgType.ToArray()).Invoke(businessObject, args);
                }
                else
                {
                    method.Invoke(businessObject, args);
                }
            }
            catch (Exception exThread)
            {
                ex = exThread;
            }
            //结果由参数带回
            e.Result = new object[] { completeMethod, ex, arguments[5] };
        }

        /// <summary>
        /// 获得目标方法
        /// </summary>
        /// <param name="svcType">方法所在类型</param>
        /// <param name="methodName">方法名</param>
        /// <param name="argTypes">参数类型集合</param>
        /// <returns>方法信息</returns>
        private static MethodInfo GetTarMethod(Type svcType, string methodName, Type[] argTypes)
        {
            foreach (var item in svcType.GetInterfaces())
            {
                var method = item.GetMethod(methodName, argTypes);
                if (method != null)
                {
                    return method;
                }
            }
            return null;
        }

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //取出结果
            var results = e.Result as object[];
            try
            {
                //取出回调方法
                var method = results[0] as Action<Exception>;
                if (results[1] != null)
                {
                    var exThread = results[1] as Exception;
                    if (exThread.InnerException != null)
                    {
                        method(exThread.InnerException);
                    }
                    else
                    {
                        method(exThread);
                    }
                }
                else
                {
                    method(null);
                }
            }
            //应对回调时回调对象已被销毁
            catch (Exception exc)
            {
                //把除了访问已释放的资源异常吃掉外,其他异常抛出,方便调试
                if (!(exc is ObjectDisposedException))
                {
                    throw exc;
                }
            }
            finally
            {
                //及时清除引用,防止以后错误调用的干扰
                SelfBackgroundWorker = null;
                if (!((bool)results[2]))
                {
                    InnerBackGroundWorker.RunWorkerAsync();
                }
            }
        }
    }
    #endregion

    #region 带返回类型的异步工具-含报告
    ///<summary  NoteObject="Class">
    /// [功能描述:管理的带报告带返回值的异步工具类,对于调用异步时使用单独线程的操作就千万不要调用Report方法,因为单独线程已经不处于托管环境了,此时调Report会干扰托管的线程] <para/>
    /// [创建者:张联珠] <para/>
    /// [创建时间:2014年4月11日] <para/>
    ///<说明>
    ///  [说明:修改原工具类
    ///  使用说明:后台操作方法不要访问UI资源]<para/>
    ///</说明>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///</summary>
    public static class ManagedAsyncUtilsWithReport<TResult, TReport>
    {
        #region 字段
        /// <summary>
        /// 私有的静态工作对象
        /// </summary>
        private static BackgroundWorker SelfBackgroundWorker = null;

        /// <summary>
        /// 通知回调
        /// </summary>
        private static Action<TReport, Exception> Reports;
        #endregion

        #region 构造函数

        /// <summary>
        /// 使用前初始化异步工具
        /// </summary>
        public static void InitUtil(BackgroundWorker backGroundWorker)
        {
            SelfBackgroundWorker = backGroundWorker;
            SelfBackgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            SelfBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            SelfBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            //支持报告进度
            SelfBackgroundWorker.WorkerReportsProgress = true;
        }
        #endregion

        #region 对外提供的方法
        /// <summary>
        /// 异步调用
        /// </summary>
        /// <param name="invokeCompleted">回调方法委托()回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="reportChanged">通知改变的回调方法委托(该参数可以为空,为空就不通知改变,如果传入该参数不为空,可以调用Report方法来反信息)回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="businessObject">调用目标对象实例(后台方法所在类的对象)</param>
        /// <param name="methodName">后台执行的方法名称(要申明成公有,应为内部通过反射来访问,不是公有的话会访问不到。该操作方法不要访问UI资源,在回调方法里访问)</param>
        /// <param name="args">后台执行方法需要的参数(和参数顺序一样的object数组)</param>
        /// <param name="isSelfAsy">是否单独一个异步</param>
        public static void Invoke(Action<TResult, Exception> invokeCompleted, Action<TReport, Exception> reportChanged, object businessObject,
            string methodName, object[] args, bool isSelfAsy = false)
        {
            if (!isSelfAsy)
            {
                lock (InnerBackGroundWorker.Lock)
                {
                    InnerBackGroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), reportChanged, isSelfAsy });
                }
            }
            else
            {
                InitUtil(new BackgroundWorker());
                SelfBackgroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil), reportChanged, isSelfAsy });
            }
        }

        /// <summary>
        /// 报告事件
        /// </summary>
        /// <param name="reportInfo">报告内容</param>
        /// <param name="ex">报告异常</param>
        public static void Report(TReport reportInfo, Exception ex)
        {
            object[] args = new object[] { reportInfo, ex };
            SelfBackgroundWorker.ReportProgress(0, args);
        }

        #endregion

        #region 内部方法

        /// <summary>
        /// BackgroundWorker的后台方法
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">参数</param>
        private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //获得参数数组
            var arguments = e.Argument as object[];
            //获得回调方法
            var completeMethod = arguments[0];
            //获得业务实体
            var businessObject = arguments[1];
            //获得方法名
            var methodName = arguments[2] as string;
            //获得参数
            var args = arguments[3] as object[];
            //通知回调
            Reports = arguments[5] as Action<TReport, Exception>;
            //存放结果
            object result = null;
            //存放异常
            Exception ex = null;
            try
            {
                //参数类型集合
                List<Type> lstArgType = new List<Type>();
                //把所有参数的类型填入集合
                if (args != null && args.Length > 0)
                {
                    for (int i = 0; i < args.Length; i++)
                    {
                        lstArgType.Add(args[i].GetType());
                    }
                }
                //获得方法
                var method = GetTarMethod(businessObject.GetType(), methodName, lstArgType.ToArray());
                //如果没找到该方法,直接执行该业务实体的方法
                if (method == null)
                {
                    //执行,并把结果赋给结果对象
                    result = businessObject.GetType().GetMethod(methodName, lstArgType.ToArray()).Invoke(businessObject, args);
                }
                //如果找到了方法,则通过接口调方法
                else
                {
                    result = method.Invoke(businessObject, args);
                }
            }
            catch (Exception exThread)
            {
                ex = exThread;
            }
            //结果由参数带回
            e.Result = new object[] { result, completeMethod, ex, arguments[6] };
        }

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var results = e.Result as object[];
            //取出结果
            var result = results[0];
            Exception ex = null;
            //如果结果带出的异常不为空
            if (results[2] != null)
            {
                var exThread = results[2] as Exception;
                //如果内部异常不为空,则取内部异常
                if (exThread.InnerException != null)
                {
                    ex = exThread.InnerException;
                }
                //否则直接取总异常
                else
                {
                    ex = exThread;
                }
            }
            try
            {
                //取出回调委托
                Action<TResult, Exception> method = results[1] as Action<TResult, Exception>;
                //如果返回结果为空,传该类型的默认值
                if (result == null)
                {
                    method(default(TResult), ex);
                }
                //否则传带出的结果
                else
                {
                    method((TResult)result, ex);
                }
            }
            //应对回调时回调对象已被销毁
            catch (Exception exc)
            {
                //把除了访问已释放的资源异常吃掉外,其他异常抛出,方便调试
                if (!(exc is ObjectDisposedException))
                {
                    throw exc;
                }
            }
            finally
            {
                //及时清除引用,防止以后错误调用的干扰
                SelfBackgroundWorker = null;
                if(!((bool)results[3]))
                {
                    InnerBackGroundWorker.RunWorkerAsync();
                }
            }
        }


        /// <summary>
        /// 进度改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //如果通知回调不为空
            if (Reports != null)
            {
                //提出方法参数
                var arguments = e.UserState as object[];
                Reports((TReport)arguments[0], arguments[1] as Exception);
            }
        }

        /// <summary>
        /// 获得目标方法
        /// </summary>
        /// <param name="svcType">方法所在类型</param>
        /// <param name="methodName">方法名</param>
        /// <param name="argTypes">参数类型集合</param>
        /// <returns>方法信息</returns>
        private static MethodInfo GetTarMethod(Type svcType, string methodName, Type[] argTypes)
        {
            //获取由当前实体所实现的接口集合
            foreach (var item in svcType.GetInterfaces())
            {
                //通过名称和类型找方法
                var method = item.GetMethod(methodName, argTypes);
                //找到方法就返回
                if (method != null)
                {
                    return method;
                }
            }
            return null;
        }
        #endregion

    }


    #endregion

    #region 不带返回类型的异步工具-含报告
    ///<summary  NoteObject="Class">
    /// [功能描述:管理的的带报告的异步工具类,对于调用异步时使用单独线程的操作就千万不要调用Report方法,因为单独线程已经不处于托管环境了,此时调Report会干扰托管的线程] <para/>
    /// [创建者:张联珠] <para/>
    /// [创建时间:2014年4月11日] <para/>
    ///<说明>
    ///  [说明:修改原工具类
    ///  使用说明:后台操作方法不要访问UI资源]<para/>
    ///</说明>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///<修改记录>
    ///    [修改时间:本次修改时间]<para/>
    ///    [修改内容:本次修改内容]<para/>
    ///</修改记录>
    ///</summary>
    public static class ManagedAsyncUtilsWithReport<TReport>
    {
        #region 字段
        /// <summary>
        /// 私有的静态工作对象
        /// </summary>
        private static BackgroundWorker SelfBackgroundWorker = null;

        /// <summary>
        /// 通知回调
        /// </summary>
        private static Action<TReport, Exception> Reports;

        #endregion

        #region 构造函数

        /// <summary>
        /// 使用前初始化异步工具
        /// </summary>
        public static void InitUtil(BackgroundWorker backGroundWorker)
        {
            SelfBackgroundWorker = backGroundWorker;
            SelfBackgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            SelfBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            SelfBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            //支持报告进度
            SelfBackgroundWorker.WorkerReportsProgress = true;
        }
        #endregion

        #region 对外提供的方法

        /// <summary>
        /// 异步调用
        /// </summary>
        /// <param name="invokeCompleted">回调方法委托()回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="reportChanged">通知改变的回调方法委托(该参数可以为空,为空就不通知改变,如果传入该参数不为空,可以调用Report方法来反信息)回调的方法可以不是公有的,因为使用委托了</param>
        /// <param name="businessObject">调用目标对象实例(后台方法所在类的对象)</param>
        /// <param name="methodName">后台执行的方法名称(要申明成公有,应为内部通过反射来访问,不是公有的话会访问不到。该操作方法不要访问UI资源,在回调方法里访问)</param>
        /// <param name="args">后台执行方法需要的参数(和参数顺序一样的object数组)</param>
        /// <param name="isSelfAsy">是否单独一个异步</param>
        public static void Invoke(Action<Exception> invokeCompleted, Action<TReport, Exception> reportChanged, object businessObject,
            string methodName, object[] args, bool isSelfAsy=false)
        {
            if (!isSelfAsy)
            {
                lock (InnerBackGroundWorker.Lock)
                {
                    InnerBackGroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil),reportChanged, isSelfAsy });
                }
            }
            else
            {
                InitUtil(new BackgroundWorker());
                SelfBackgroundWorker.RunWorkerAsync(new object[] { invokeCompleted, businessObject, methodName, args, new InitAsyUtil(InitUtil),reportChanged ,isSelfAsy });
            }
        }

        /// <summary>
        /// 报告事件
        /// </summary>
        /// <param name="reportInfo">报告内容</param>
        /// <param name="ex">报告异常</param>
        public static void Report(TReport reportInfo, Exception ex)
        {
            object[] args = new object[] { reportInfo, ex };
            SelfBackgroundWorker.ReportProgress(0, args);
        }
        #endregion

        #region 内部方法

        /// <summary>
        /// 后台工作方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //提出方法参数
            var arguments = e.Argument as object[];
            //提出回调委托
            var completeMethod = arguments[0];
            //提出调用方法的对象
            var businessObject = arguments[1];
            //提出调用方法的名称
            var methodName = arguments[2] as string;
            //提出调用方法的参数
            var args = arguments[3] as object[];
            //通知回调
            Reports = arguments[5] as Action<TReport, Exception>;
            //异常
            Exception ex = null;
            try
            {
                //存所有的参数类型
                List<Type> lstArgType = new List<Type>();
                if (args != null && args.Length > 0)
                {
                    for (int i = 0; i < args.Length; i++)
                    {
                        lstArgType.Add(args[i].GetType());
                    }
                }
                //获得调用方法
                var method = GetTarMethod(businessObject.GetType(), methodName, lstArgType.ToArray());
                if (method == null)
                {
                    businessObject.GetType().GetMethod(methodName, lstArgType.ToArray()).Invoke(businessObject, args);
                }
                else
                {
                    method.Invoke(businessObject, args);
                }
            }
            catch (Exception exThread)
            {
                ex = exThread;
            }
            //结果由参数带回
            e.Result = new object[] { completeMethod, ex, arguments[6] };
        }

        /// <summary>
        /// 获得目标方法
        /// </summary>
        /// <param name="svcType">方法所在类型</param>
        /// <param name="methodName">方法名</param>
        /// <param name="argTypes">参数类型集合</param>
        /// <returns>方法信息</returns>
        private static MethodInfo GetTarMethod(Type svcType, string methodName, Type[] argTypes)
        {
            foreach (var item in svcType.GetInterfaces())
            {
                var method = item.GetMethod(methodName, argTypes);
                if (method != null)
                {
                    return method;
                }
            }
            return null;
        }



        /// <summary>
        /// 进度改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //如果通知回调不为空
            if (Reports != null)
            {
                //提出方法参数
                var arguments = e.UserState as object[];
                Reports((TReport)arguments[0], arguments[1] as Exception);
            }
        }

        /// <summary>
        /// 回调方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //取出结果
            var results = e.Result as object[];
            try
            {
                //取出回调方法
                var method = results[0] as Action<Exception>;
                if (results[1] != null)
                {
                    var exThread = results[1] as Exception;
                    if (exThread.InnerException != null)
                    {
                        method(exThread.InnerException);
                    }
                    else
                    {
                        method(exThread);
                    }
                }
                else
                {
                    method(null);
                }
            }
            //应对回调时回调对象已被销毁
            catch(Exception exc)
            {
                //把除了访问已释放的资源异常吃掉外,其他异常抛出,方便调试
                if (!(exc is ObjectDisposedException))
                {
                    throw exc;
                }
            }
            finally
            {
                //及时清除引用,防止以后错误调用的干扰
                SelfBackgroundWorker = null;
                if (!((bool)results[2]))
                {
                    InnerBackGroundWorker.RunWorkerAsync();
                }
            }
        }

        #endregion
    }
    #endregion
   
}

这样就可以把需要线程执行的逻辑交给管理类执行了。还是上一篇线程的例子接着写。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Util;

namespace ThreadUI
{
    /// <summary>
    /// 写日志委托
    /// </summary>
    /// <param name="info"></param>
    public delegate void WriteInfoDelegate(string info);

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 加载方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //用线程写文本
            //Thread t = new Thread(WriteTxt);
            //t.Start();
            //创建异步工具类的回调委托
            Action<Exception> workerCompleted = new Action<Exception>(DealReturn);
            //创建异步工具类的回调委托
            Action<LogDto, Exception> workerCahnge = new Action<LogDto, Exception>(DealChange);
            //组装参数
            object[] paras = new object[] { };
            //初始化工具
            ManagedAsyncUtilsWithReport<LogDto>.InitUtil(new BackgroundWorker());
            //这里启动的线程是被管理的,多个调用之间是先后执行的。用来实现UI即需要线程,又不希望线程之间乱序执行
            ManagedAsyncUtilsWithReport<LogDto>.Invoke(workerCompleted, workerCahnge, this, "StartMonitor", paras);
            ManagedAsyncUtilsWithReport<LogDto>.Invoke(workerCompleted, workerCahnge, this, "StartMonitor1", paras);

        }

        /// <summary>
        /// 开始监听
        /// </summary>
        public void StartMonitor()
        {
            //循环通知界面
            for (int i = 0; i < 100; i++)
            {
                LogDto dt = new LogDto();
                dt.Time = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                dt.Info = "第" + i + "行\n";
                ManagedAsyncUtilsWithReport<LogDto>.InitUtil(new BackgroundWorker());
                //通知界面改变
                ManagedAsyncUtilsWithReport<LogDto>.Report(dt, null);
            }
        }

        /// <summary>
        /// 开始监听
        /// </summary>
        public void StartMonitor1()
        {
            //循环通知界面
            for (int i = 101; i < 200; i++)
            {
                LogDto dt = new LogDto();
                dt.Time = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
                dt.Info = "第" + i + "行\n";
                ManagedAsyncUtilsWithReport<LogDto>.InitUtil(new BackgroundWorker());
                //通知界面改变
                ManagedAsyncUtilsWithReport<LogDto>.Report(dt, null);
            }
        }

        /// <summary>
        /// 处理数据改变
        /// </summary>
        /// <param name="ex">异常信息</param>
        public void DealChange(LogDto dto, Exception ex)
        {
            string log = dto.Time + " " + dto.Info;
            //组装参数
            object[] paras = new object[] { log };
            //在UI线程执行委托
            this.Invoke(new WriteInfoDelegate(SetTxt), paras);
        }

        /// <summary>
        /// 处理返回的回调
        /// </summary>
        /// <param name="ex"></param>
        public void DealReturn(Exception ex)
        {
            richTextBox1.Text += "运行一轮完毕!\n";
            //创建异步工具类的回调委托
            //Action<Exception> workerCompleted = new Action<Exception>(DealReturn);
            //创建异步工具类的回调委托
            //Action<LogDto, Exception> workerCahnge = new Action<LogDto, Exception>(DealChange);
            //组装参数
            //object[] paras = new object[] { };
            //初始化工具
            //ManagedAsyncUtilsWithReport<LogDto>.InitUtil(new BackgroundWorker());
            //ManagedAsyncUtilsWithReport<LogDto>.Invoke(workerCompleted, workerCahnge, this, "StartMonitor", paras);
        }

        /// <summary>
        /// 写日志代理方法
        /// </summary>
        /// <param name="info"></param>
        public void WriteInfoProxy(string info)
        {
            //组装参数
            object[] paras = new object[] { info };
            //在UI线程执行委托
            this.Invoke(new WriteInfoDelegate(SetTxt), paras);
        }

        /// <summary>
        /// 操作控件逻辑
        /// </summary>
        /// <param name="info"></param>
        public void SetTxt(string info)
        {
            richTextBox1.Text += info;
        }

        /// <summary>
        /// 写文本
        /// </summary>
        public void WriteTxt()
        {
            for (int i = 0; i < 100; i++)
            {
                WriteInfoProxy("第" + i + "行\n");
            }

        }

        /// [功能描述: 监听日志实体,用来存监听的日志数据]<br></br>
        /// [创建者:   张联珠]<br></br>
        /// [创建时间: 2015-7-9]<br></br>
        /// <说明>
        ///    
        /// </说明>
        /// <修改记录>
        ///     <修改时间></修改时间>
        ///     <修改内容>
        ///            
        ///     </修改内容>
        /// </修改记录>
        /// </summary>
        [Serializable]
        public class LogDto
        {
            /// <summary>
            /// 时间
            /// </summary>
            public string Time
            {
                get;
                set;
            }


            /// <summary>
            /// 信息
            /// </summary>
            public string Info
            {
                get;
                set;
            }
        }

    }
}

在图的地方开启了两个线程,如果不管理线程,那么第一个线程输出的1-100和第二个线程输出的100-200肯定有重叠了。管理之后就不会重叠了。
在这里插入图片描述

在这里插入图片描述

这就是线程管理类的妙处了,既保证不卡UI,又保证线程之间有序性。

iMedicalLIS监听程序的异步就是基于线程管理类构建的,没有之间创建Thread。此逻辑稳定,为数千设备监听服务。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值