近期項目中需在用戶點擊按鈕后,延時執行代碼邏輯,避免頻繁操作。網上沒找到有關 C# SetTimeout 官方API , 於是通過異步線程,動手實現一個。方案如下,如果同一個DelayedProcess 對象連續調用 SetTimeout 多次 ,默認取消前一次調用。
public class DelayedProcess<Req,Rsp> { public delegate void ExcuteMethod(Result rsp); CancellationTokenSource tokenSource; public class Result { public Req request { get; set; } public Rsp response { get; set; } /// <summary> /// 拋出異常信息 /// </summary> public Exception ex; /// <summary> /// 是否延時執行成功 /// </summary> public bool IsSuccess { get; set; } } async void TaskDelay(int timeout, CancellationToken token, ExcuteMethod method, Result rsp) { try { await Task.Delay(timeout, token); rsp.IsSuccess = true; rsp.ex = null; } catch (Exception ex) { rsp.ex = ex; rsp.IsSuccess = false; } finally { method(rsp); } } public void SetTimeout(int timeout, ExcuteMethod method, Result rsp) { Cancel(); tokenSource = new CancellationTokenSource(); TaskDelay(timeout, tokenSource.Token, method , rsp); } public void Cancel() { if (tokenSource != null && !tokenSource.IsCancellationRequested) { tokenSource.Cancel(); } } }
調用示例:
DelayedProcess<string, string> dp = new DelayedProcess<string, string>(); private void button1_Click(object sender, EventArgs e) { Console.WriteLine("{0}:{1}", DateTime.Now, "開始請求"); dp.SetTimeout(2000, (arg) => { if (arg.IsSuccess) { Console.WriteLine("{0}:延時執行{1}", DateTime.Now, arg.request); } else { Console.WriteLine("{0}:延時失敗,{1}", DateTime.Now, arg.ex.Message); } }, new DelayedProcess<string, string>.Result() { request = "1111" }); }