C#异步工具类及一点小小的重构经验

王朝学院·作者佚名  2016-08-27  
宽屏版  字体: 小 | 中 | 大 | 超大  

2015年新年第一篇随笔,祝福虽然有些晚,但诚意还在:新年快乐。

今天主要是想分享一异步工具类,在C/S架构中、先进行网络资源异步访问,然后将回调函数Invoke到UI线程中进行UI处理。

这样的场景是及其常见的,因此特意封装了一工具类,用以简化操作。

///<summary>///异步工具类///</summary>publicclassTaskTools

{///<summary>///是否 在执行回调函数之前修改Running状态///</summary>publicboolChangeRunningStateBeforeCallback {get;PRivateset; }///<summary>///是否 正在执行异步任务///</summary>publicboolRunning {get;privateset; }publicTaskTools()

:this(false)

{

}///<summary>//////</summary>///<param name="changeRunningStateBeforeCallback">是否 在执行回调函数之前修改Running状态 默认值false</param>publicTaskTools(boolchangeRunningStateBeforeCallback)

{this.ChangeRunningStateBeforeCallback =changeRunningStateBeforeCallback;

}///<summary>///执行异步任务///</summary>///<typeparam name="T">异步任务返回值类型</typeparam>///<param name="control">操作UI时需要Invoke的控件</param>///<param name="asyncFunc">将要执行的任务任务</param>///<param name="callback">异步任务执行完毕后执行的回调函数</param>publicvoidRun<T>(Control control, Func<T> asyncFunc, Action<T>callback)

{if(this.Running)thrownewInvalidOperationException("the task is running");try{this.Running =true;

Task<T> task =newTask<T>(() =>{try{returnasyncFunc();

}catch(Exception ex)

{

Console.WriteLine(ex.Message);returndefault(T);

}

});

task.Start();

TaskContinue<T>(control, task, callback);

}catch(Exception ex)

{

Console.WriteLine(ex.Message);

}finally{this.Running =false;

}

}///<summary>///执行异步任务///</summary>///<typeparam name="T">异步任务返回值类型</typeparam>///<param name="control">操作UI时需要Invoke的控件</param>///<param name="args">异步任务的传入参数</param>///<param name="asyncFunc">将要执行的任务任务</param>///<param name="callback">异步任务执行完毕后执行的回调函数</param>publicvoidRun<T>(Control control,objectargs, Func<object, T> asyncFunc, Action<T>callback)

{if(this.Running)thrownewInvalidOperationException("the task is running");try{this.Running =true;

Task<T> task =newTask<T>((lambdaObj) =>{try{returnasyncFunc(lambdaObj);

}catch(Exception ex)

{

Console.WriteLine(ex.Message);returndefault(T);

}

}, args);

task.Start();

TaskContinue<T>(control, task, callback);

}catch(Exception ex)

{

Console.WriteLine(ex.Message);

}finally{this.Running =false;

}

}///<summary>///延时执行某任务///</summary>///<param name="control">操作UI时需要Invoke的控件</param>///<param name="milliSecond">将要延时执行的毫秒数</param>///<param name="callback">异步任务执行完毕后执行的回调函数</param>publicvoidDelayedRun(intmilliSecond, Control control, Action callback)

{this.Run<int>(control, () =>{

Thread.Sleep(milliSecond); // 4.0 类库returnmilliSecond;

}, (time)=>{

callback();

});

}///<summary>///Control.Invoke方法的简易封装///</summary>///<typeparam name="T">参数类型</typeparam>///<param name="control"></param>///<param name="args"></param>///<param name="action"></param>publicstaticvoidControlInvoke<T>(Control control, T args, Action<T>action)

{try{

Invoke<T>(control, args, action);

}catch(Exception ex)

{

Console.WriteLine(ex.Message);

}

}///<summary>///异步任务完成后继续执行...///</summary>///<typeparam name="T"></typeparam>///<param name="control"></param>///<param name="task"></param>///<param name="callback"></param>privatevoidTaskContinue<T>(Control control, Task<T> task, Action<T>callback)

{

task.ContinueWith((lambdaAction)=>{if(this.ChangeRunningStateBeforeCallback)

{this.Running =false;

}try{if(callback !=null)

{//有UI控件 则将回调函数注入到UI控件的相关线程中去执行if(control !=null)

{

TaskTools.Invoke<T>(control, lambdaAction.Result, callback);

}else{//否则在当前线程内执行 回调函数callback(lambdaAction.Result);

}

}

}catch(Exception ex)

{

Console.WriteLine(ex.Message);

}finally{this.Running =false;

}

});

}///<summary>///Control.Invoke方法的简易封装///注意 无 Try Catch///</summary>///<typeparam name="T">参数类型</typeparam>///<param name="control"></param>///<param name="args"></param>///<param name="action"></param>privatestaticvoidInvoke<T>(Control control, T args, Action<T>action)

{//control为空,在当前线程内执行该actionif(control ==null)

{

action(args);return;

}//控件正在释放或者已经被释放则不执行actionif(control.Disposing ||control.IsDisposed)return;if(control.InvokeRequired)

{

control.Invoke(action,newobject[] { args });

}else{

action(args);

}

}

}

该工具类的使用,我想应该很简单吧。不过,我想借这个机会说一点小小的重构经验:委托类型(Action Func等等)的参数、尽量放在方法参数列表的最后边。

原因是:当直接使用Lambda表达式做参数时,格式化后的代码看起来更加优雅,更加易于阅读。例如:

重构前:

TaskTools task =newTaskTools(true);//延时 30 毫秒加载task.DelayedRun(() =>{//... 其他操作//延时 30 毫秒加载task.DelayedRun(() =>{//... 其他操作},30,this.pnlMainFill);

},30,this.pnlMainFill);

重构后:

TaskTools task =newTaskTools(true);//延时 30 毫秒加载task.DelayedRun(30,this.pnlMainFill, () =>{//... 其他操作//延时 30 毫秒加载task.DelayedRun(30,this.pnlMainFill, () =>{//... 其他操作});

});

VS重排参数列表快捷键: CTRL + R, O。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有