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

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

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

    /// <summary>
/// 异步工具类
/// </summary>
public class TaskTools
{
/// <summary>
/// 是否 在执行回调函数之前修改Running状态
/// </summary>
public bool ChangeRunningStateBeforeCallback { get; private set; } /// <summary>
/// 是否 正在执行异步任务
/// </summary>
public bool Running { get; private set; } public TaskTools()
: this(false)
{ } /// <summary>
///
/// </summary>
/// <param name="changeRunningStateBeforeCallback">是否 在执行回调函数之前修改Running状态 默认值false</param>
public TaskTools(bool changeRunningStateBeforeCallback)
{
this.ChangeRunningStateBeforeCallback = changeRunningStateBeforeCallback;
} /// <summary>
/// 执行异步任务
/// </summary>
/// <typeparam name="T">异步任务返回值类型</typeparam>
/// <param name="control">操作UI时需要Invoke的控件</param>
/// <param name="asyncFunc">将要执行的任务任务</param>
/// <param name="callback">异步任务执行完毕后执行的回调函数</param>
public void Run<T>(Control control, Func<T> asyncFunc, Action<T> callback)
{
if (this.Running)
throw new InvalidOperationException(" the task is running ");
try
{
this.Running = true;
Task<T> task = new Task<T>(() =>
{
try
{
return asyncFunc();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return default(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>
public void Run<T>(Control control, object args, Func<object, T> asyncFunc, Action<T> callback)
{
if (this.Running)
throw new InvalidOperationException(" the task is running "); try
{
this.Running = true;
Task<T> task = new Task<T>((lambdaObj) =>
{
try
{
return asyncFunc(lambdaObj);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return default(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>
public void DelayedRun(int milliSecond, Control control, Action callback)
{
this.Run<int>(control, () =>
{
Thread.Sleep(milliSecond); // 4.0 类库
return milliSecond;
}, (time) =>
{
callback();
});
} /// <summary>
/// Control.Invoke方法的简易封装
/// </summary>
/// <typeparam name="T">参数类型</typeparam>
/// <param name="control"></param>
/// <param name="args"></param>
/// <param name="action"></param>
public static void ControlInvoke<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>
private void TaskContinue<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>
private static void Invoke<T>(Control control, T args, Action<T> action)
{
// control为空,在当前线程内执行该action
if (control == null)
{
action(args);
return;
} // 控件正在释放或者已经被释放则不执行action
if (control.Disposing || control.IsDisposed)
return; if (control.InvokeRequired)
{
control.Invoke(action, new object[] { args });
}
else
{
action(args);
}
}
}

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

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

重构前:

            TaskTools task = new TaskTools(true);

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

重构后:

            TaskTools task = new TaskTools(true);

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

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

C# 异步工具类 及一点小小的重构经验的更多相关文章

  1. C#操作Control异步工具类

    /// <summary> /// 异步工具类 /// </summary> public class TaskTools { /// <summary> /// ...

  2. Hibernate.基础篇《一》.Hibernate工具类.

    Hibernate.基础篇<一>.Hibernate工具类. 话述: Hibernate.基础篇第一篇,前面是代码.后面再加理论&实践. Hibernate使用的版本是:5.x,在 ...

  3. Android消息机制——时钟显示和异步处理工具类(AsyncTask)

    1. 时钟显示 定义布局文件——activity_my_analog_clock_thread_demo.xml <?xml version="1.0" encoding=& ...

  4. 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...

  5. c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习

    c#中@标志的作用   参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...

  6. JDBC实例--工具类升级,使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全

    直接使用JDBC访问数据库时,需要避免以下隐患: 1. 每一次数据操作请求都需要建立数据库连接.打开连接.存取数据和关闭连接等步骤.而建立和打开数据库连接是一件既耗资源又费时的过程,如果频繁发生这种数 ...

  7. Android基础工具类重构系列一Toast

    前言: 一直在考虑写一下Android实际项目中的一些总结,翻看CSDN博客,上一篇已经是一年多曾经. 本系列定位Android基础工具类重构.旨在记录实际项目中经经常使用到的一些工具类,比方Toas ...

  8. 从接口自动化测试框架设计到开发(二)操作json文件、重构json工具类

    用例模板里的请求数据多,看起来很乱,所以可以通过访问另外一个文件的方式获取请求数据 把请求数据都放在一个json文件中 取出login的内容: import json fp = open('G:/un ...

  9. Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!

    Go/Python/Erlang编程语言对比分析及示例   本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...

随机推荐

  1. Javascript定时器学习笔记

    掌握定时器工作原理必知:JavaScript引擎是单线程运行的,浏览器无论在什么时候都只且只有一个线程在运行JavaScript程序. 常言道:setTimeout和setInterval是伪线程. ...

  2. Caliburn实现MVVM模式的编程

    引言:什么是Caliburn ? 一个夜晚,一处教堂,人们忏悔结束后抬头看到一把宝剑插在一块石头上.石上字述“英格兰人,凡能从石头上拔出剑者,为王者!”,Caliburn就是英格兰人心中的石中剑,这把 ...

  3. java系统性能分析

    netstat -ano | findstr 31900 注意最后是pid 堆栈的作用: 线程死锁分析 辅助CPU过高分析 线程资源不足分析 性能瓶颈分析 关键线程异常退出 Windows:在运行ja ...

  4. 30分钟带你快速入门MySQL教程

    这是一篇真正适合初学者的MySQL数据库入门文章,哪怕你从来没有接触过数据库,或者说你从来没有听说过有数据库这东西,请一定要相信我,我当时就是这么过来的. 如果你刚开始接触MySQL数据库,或者你需要 ...

  5. atitit.错误:找不到或无法加载主类 的解决 v4 qa15.doc

    atitit.错误:找不到或无法加载主类 的解决 v4 qa15.doc 1.1. 修改此java文件,让他启动编译,还是不能生成了新的class, 1.2. 估计ide调试锁死class ,查看de ...

  6. salesforce 零基础学习(三十六)通过Process Builder以及Apex代码实现锁定记录( Lock Record)

    上一篇内容是通过Process Builder和Approval Processes实现锁定记录的功能,有的时候,往往锁定一条记录需要很多的限制条件,如果通过Approval Processes的条件 ...

  7. Servlet开发技术,创建,以及Servlet的配置,web.xml的配置

    直接上图,不废话!!! 第一:首先在Eclipse的包资源管理器中,单机鼠标右键,在弹出的快捷键菜单中选择“新建”/Servlet命令,在弹出的对话框中输入新建的Servlet所在的包和类名,然后单击 ...

  8. VMware Workstation cannot connect to the virtual machine 解决方案

    今天 打开虚拟机 忽然遇到这个问题: VMware Workstation cannot connect to the virtual machine. Make sure you have righ ...

  9. DOM_05之DOM、BOM常用对象

    1.HTML DOM常用对象之Table:①创建:createTHead():createTBody():createTFoot():②删除:deleteTHead():deleteTFoot():③ ...

  10. iOS苹果企业证书被撤销以及启用与管理

    在国内, 积分墙以及各大助手(爱思助手, 91苹果助手, XY苹果助手, PP助手, 快用助手)等业务领域都在使用,苹果对证书的使用越来越严格.简单的分析一下,证书被封的原因.   一般证书被封会收到 ...