C # asynchronous tool class and a little refactoring experience,
The first article of the new year in 2015, wishing you a little late, but your sincerity is still at: Happy New Year.
Today I want to share an asynchronous tool class. In the C/S architecture, I first perform asynchronous access to network resources and then call the callback function Invoke to the UI thread for UI processing.
This is a common scenario. Therefore, a tool class is specially encapsulated to simplify operations.
/// <Summary> /// asynchronous tool class /// </summary> public class TaskTools {// <summary> /// whether to modify the Running status before executing the callback function /// </summary> public bool ChangeRunningStateBeforeCallback {get; private set;} // <summary> // whether an asynchronous task is being executed // </summary> public bool Running {get; private set;} public TaskTools (): this (false) {}/// <summary> //// </summary> /// <param name = "changeRunningStateBeforeCallback"> indicates whether the execution is performed The default value of modifying the Running status before the row callback function is false </param> public TaskTools (bool changeRunningStateBeforeCallback) {this. changeRunningStateBeforeCallback = changeRunningStateBeforeCallback ;} /// <summary> /// execute an asynchronous task /// </summary> /// <typeparam name = "T"> return value type of an asynchronous task </typeparam> // /<param name = "control"> Invoke control </param> // <param name = "asyncFunc"> task to be executed </param> /// <param name = "callback"> callback function executed after the asynchronous task is executed </pa Ram> 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 (Exce Ption ex) {Console. writeLine (ex. message);} finally {this. running = false ;}} /// <summary> /// execute an asynchronous task /// </summary> /// <typeparam name = "T"> return value type of an asynchronous task </typeparam> // /<param name = "control"> controls that require Invoke during UI Operations </param> // <param name = "args"> input parameters of asynchronous tasks </param> /// <param name = "asyncFunc"> task to be executed </param> /// <param name = "callback"> callback function executed after the asynchronous task is executed </param> public void Run <T> (Control 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 (Ti On ex) {Console. writeLine (ex. message);} finally {this. running = false ;}} /// <summary> /// delayed execution of a task // </summary> /// <param name = "control"> Invoke control is required for UI Operations </ param> /// <param name = "milliSecond"> Number of milliseconds to be delayed </param> /// <param name = "callback"> after an asynchronous task is executed </param> public void DelayedRun (int milliSecond, control control, Action callback) {this. run <int> (control, () => {Thread. sleep (milliSeco Nd); // 4.0 class library return milliSecond ;}, (time) =>{ callback () ;}}/// <summary> // Control. simple encapsulation of the Invoke method /// </summary> /// <typeparam name = "T"> parameter type </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 (Excep Tion ex) {Console. writeLine (ex. message) ;}/// <summary> // continue after the asynchronous task is completed... /// </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) {t His. Running = false;} try {if (callback! = Null) {// if a UI control exists, the callback function is injected into the relevant thread of the UI control to execute if (control! = Null) {TaskTools. invoke <T> (control, lambdaAction. result, callback);} else {// otherwise, the callback function callback (lambdaAction) is executed in the current thread. result) ;}} catch (Exception ex) {Console. writeLine (ex. message);} finally {this. running = false ;}}) ;}/// <summary> // Control. simple encapsulation of the Invoke method // note that no Try Catch is available /// </summary> /// <typeparam name = "T"> parameter type </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 is empty. Execute this action in the current thread if (control = null) {action (args); return ;} // if the control is being released or has been released, no action if (control. disposing | control. isDisposed) return; if (control. invokeRequired) {control. invoke (action, new object [] {args}) ;}else {action (args );}}}
The usage of this tool class should be very simple. However, I 'd like to take this opportunity to sayA little refactoring experience: parameters of the delegate type (such as Action Func) should be placed at the end of the method parameter list.
The reason is: When Lambda expressions are used directly for parameters, the formatted code looks more elegant and easier to read. For example:
Before reconstruction:
TaskTools task = new TaskTools (true); // The task is loaded with a delay of 30 milliseconds. delayedRun () => {//... other operations // The task is loaded with a latency of 30 milliseconds. delayedRun () => {//... other operations}, 30, this. pnlMainFill);}, 30, this. pnlMainFill );
After reconstruction:
TaskTools task = new TaskTools (true); // The task is loaded with a delay of 30 milliseconds. delayedRun (30, this. pnlMainFill, () => {//... other operations // The task is loaded with a latency of 30 milliseconds. delayedRun (30, this. pnlMainFill, () => {//... other operations });});
Shortcut Keys for VS rearranging parameter list: CTRL + R, O.