2015年新年第一篇隨筆, 祝福雖然有些晚,但誠意還在:新年快樂。
今天主要是想分享一異步工具類,在C/S架構(gòu)中、先進(jìn)行網(wǎng)絡(luò)資源異步訪問,然后將回調(diào)函數(shù) Invoke到UI線程中進(jìn)行UI處理。
這樣的場景是及其常見的,因此特意封裝了一工具類,用以簡化操作。
/// <summary> /// 異步工具類 /// </summary> public class TaskTools { /// <summary> /// 是否 在執(zhí)行回調(diào)函數(shù)之前修改Running狀態(tài) /// </summary> public bool ChangeRunningStateBeforeCallback { get; PRivate set; } /// <summary> /// 是否 正在執(zhí)行異步任務(wù) /// </summary> public bool Running { get; private set; } public TaskTools() : this(false) { } /// <summary> /// /// </summary> /// <param name="changeRunningStateBeforeCallback">是否 在執(zhí)行回調(diào)函數(shù)之前修改Running狀態(tài) 默認(rèn)值false</param> public TaskTools(bool changeRunningStateBeforeCallback) { this.ChangeRunningStateBeforeCallback = changeRunningStateBeforeCallback; } /// <summary> /// 執(zhí)行異步任務(wù) /// </summary> /// <typeparam name="T">異步任務(wù)返回值類型</typeparam> /// <param name="control">操作UI時(shí)需要Invoke的控件</param> /// <param name="asyncFunc">將要執(zhí)行的任務(wù)任務(wù)</param> /// <param name="callback">異步任務(wù)執(zhí)行完畢后執(zhí)行的回調(diào)函數(shù)</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> /// 執(zhí)行異步任務(wù) /// </summary> /// <typeparam name="T">異步任務(wù)返回值類型</typeparam> /// <param name="control">操作UI時(shí)需要Invoke的控件</param> /// <param name="args">異步任務(wù)的傳入?yún)?shù)</param> /// <param name="asyncFunc">將要執(zhí)行的任務(wù)任務(wù)</param> /// <param name="callback">異步任務(wù)執(zhí)行完畢后執(zhí)行的回調(diào)函數(shù)</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> /// 延時(shí)執(zhí)行某任務(wù) /// </summary> /// <param name="control">操作UI時(shí)需要Invoke的控件</param> /// <param name="milliSecond">將要延時(shí)執(zhí)行的毫秒數(shù)</param> /// <param name="callback">異步任務(wù)執(zhí)行完畢后執(zhí)行的回調(diào)函數(shù)</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">參數(shù)類型</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> /// 異步任務(wù)完成后繼續(xù)執(zhí)行... /// </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控件 則將回調(diào)函數(shù) 注入到UI控件的相關(guān)線程中去執(zhí)行 if (control != null) { TaskTools.Invoke<T>(control, lambdaAction.Result, callback); } else { // 否則在當(dāng)前線程內(nèi)執(zhí)行 回調(diào)函數(shù) callback(lambdaAction.Result); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { this.Running = false; } }); } /// <summary> /// Control.Invoke方法的簡易封裝 /// 注意 無 Try Catch /// </summary> /// <typeparam name="T">參數(shù)類型</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為空,在當(dāng)前線程內(nèi)執(zhí)行該action if (control == null) { action(args); return; } // 控件正在釋放或者已經(jīng)被釋放則不執(zhí)行action if (control.Disposing || control.IsDisposed) return; if (control.InvokeRequired) { control.Invoke(action, new object[] { args }); } else { action(args); } } }
該工具類的使用,我想應(yīng)該很簡單吧。不過,我想借這個(gè)機(jī)會(huì)說一點(diǎn)小小的重構(gòu)經(jīng)驗(yàn):委托類型(Action Func等等)的參數(shù)、盡量放在方法參數(shù)列表的最后邊。
原因是:當(dāng)直接使用Lambda表達(dá)式做參數(shù)時(shí),格式化后的代碼看起來更加優(yōu)雅,更加易于閱讀。例如:
重構(gòu)前:
TaskTools task = new TaskTools(true); // 延時(shí) 30 毫秒加載 task.DelayedRun(() => { // ... 其他操作 // 延時(shí) 30 毫秒加載 task.DelayedRun(() => { // ... 其他操作 }, 30, this.pnlMainFill); }, 30, this.pnlMainFill);
重構(gòu)后:
TaskTools task = new TaskTools(true); // 延時(shí) 30 毫秒加載 task.DelayedRun(30, this.pnlMainFill, () => { //... 其他操作 // 延時(shí) 30 毫秒加載 task.DelayedRun(30, this.pnlMainFill, () => { //... 其他操作 }); });
VS重排參數(shù)列表快捷鍵: CTRL + R, O。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注