在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);
}