C# 中 SetTimeout 方案
近期项目中需在用户点击按钮后,延时执行代码逻辑,避免频繁操作。网上没找到有关 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" }); }