线程管理类

在Winform中如果所有逻辑都在UI线程执行的话UI很容易就会被卡住转圈未响应。为了避免界面卡死,对于费时的操作需要用线程执行。但是有一种情况是我有很多操作都要用线程后台执行来避免卡界面,但是我又不想多个线程调用无序,要求多个线程调用方法顺序执行,来打的UI的顺序执行和后台线程的顺序执行。这种情况对多个线程调用的进度管理就成了问题。为了满足这种Winform经常需要的情况,开发了线程管理类,后台管理一个执行队列,只持有一个线程来执行队列里的任务,既满足了不卡UI的要求,又满足后台执行有序的要求。

实现类

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

namespace LISMonitor
{
    #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
   
}

开启后台调用事列

 LIS.Core.Util.LogUtils.WriteDebugLog("准备异步监听");
 //创建异步工具类的回调委托
 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());
 LIS.Core.Util.LogUtils.WriteDebugLog("监听程序开启监听");
 ManagedAsyncUtilsWithReport<LogDto>.Invoke(workerCompleted, workerCahnge, this, "StartMonitor", paras);                   

回调方法

/// <summary>
/// 处理返回的回调
/// </summary>
/// <param name="ex"></param>
public void DealReturn(Exception ex)
{
    if (ex != null)
    {
        LIS.Core.Util.LogUtils.WriteDebugLog("监听过程发生错误" + ex.Message);
        //对网络错误弹窗提示,并退出程序
        if (ex.Message.Contains("没有终结点在侦听可以接受消息的"))
        {
            MessageBox.Show("网络错误,请确认电脑的连网状态!无法传输LIS数据,网络恢复后请重新打开监听程序", "iMedicalLIS监听提示");
        }
        //对网络错误弹窗提示,并退出程序
        if (ex.Message.Contains("无法连接到远程服务器"))
        {
            MessageBox.Show("网络错误,请确认电脑的连网状态!无法传输LIS数据,网络恢复后请重新打开监听程序", "iMedicalLIS监听提示");
        }
    }
    if (PreDeal.Interface.BaseDeal.DealDataNum > waringNum)
    {
        MessageBox.Show("监听程序当天调用保存数据次数超过" + waringNum + "次,请联系工程师查看是否有异常情况!", "温馨提示");
    }
    //创建异步工具类的回调委托
    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="ex">异常信息</param>
public void DealChange(LogDto dto, Exception ex)
{
    //窗口是打开状态才绑数据
    if (this.WindowState != FormWindowState.Minimized)
    {
        //组装参数
        object[] paras = new object[] { dto.Result };
        this.Invoke(new BindDataDelegate(BindData), paras);
    }
}

线程方法和通知UI

/// <summary>
/// 开始监听
/// </summary>
public void StartMonitor()
{
	LogDto dt = new LogDto();
    dt.Address = "";
    dt.Time = DateTime.Now.ToString();
	//窗口是打开状态才绑数据
    if (this.WindowState != FormWindowState.Minimized)
    {
        ManagedAsyncUtilsWithReport<LogDto>.InitUtil(new BackgroundWorker());
        //通知界面改变
        ManagedAsyncUtilsWithReport<LogDto>.Report(dt, null);
    }
    LIS.Core.Util.LogUtils.WriteDebugLog("一轮监听结束,休眠" + sleepTime + "毫秒");
    //阻塞进程
    System.Threading.Thread.Sleep(sleepTime);
    //有数据改变为活动图标
    ChangeIcon(2);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小乌鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值