首页 > 代码库 > C# 异步工具类 及一点小小的重构经验

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

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

  今天主要是想分享一异步工具类,在C/S架构中、先进行网络资源异步访问,然后将回调函数 InvokeUI线程中进行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(() =>                {                  // ... 其他操作                    }, 30, this.pnlMainFill);            }, 30, this.pnlMainFill);

重构后:

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

 

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

 

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