此处参考自阿涛的博文:http://www.cnblogs.com/HelloMyWorld/p/5526914.html

一 自己定义

基本的思路:

net中异步操作由于是交给线程来实现,因此不可能真正想js那样将一个单线程上的任务移除:如

var id=setTimeout(fun,200);

if(id>0){

  clearTimeout(id);//将一个任务从单线程的任务栈中移除,自然就做到了真正的移除任务

}

但是在net中一个任务交给线程执行后,具体什么时候执行完成我们并不确定,就算是我们把线程终止掉,如果任务执行完了,且执行完后与之关联的处理函数关系任然建立,那么其处理函数一样会执行

那么对于net这样的现状,我们只好斩断与之关联的处理函数的关系,来达到取消一个任务的或者认为他超时

同样的原理,比如我们有一个搜索框,或者地图缩放来做一些事情,其实我们在输入框中输入一段文字是非常快的,假如我们以文本发生变化就去发起网络搜索,那么其实会发起n个字符的搜索请求;

但是实际上我们想要只是最后一次发起的请求而已,那么问题就来了,这些回来的数据谁先谁后都是随机的,也就自然的出现了结果乱七八糟,那么怎么办呢?

1 同步搜索

我们可以锁定ui界面让用户不再能够发起请求:当然是一个传统并非很友好的解决

如:点击搜索按钮,调用搜索程序发起搜索,锁住ui,等待结果返回,再解锁ui将操作交给用户;

2 延时处理

比如连续的触发任务执行,那么我们就让他在小于一段时间内的触发不发起真正的请求,这种办法也只是减少无用请求而已

如:我一直点搜索按钮一直点,是的一直点,但是当我到达比如200ms的才会发起请求,之前点的都没用;

3 取消无用的处理

比如我连续发起了10次请求但是,只要最后一次的,那么我把之前的就取消掉,请求其实已经发出,只是对于结果我们丢弃掉了

如:我一直点一直点一直点,发起了10次请求,但是我每次发起请求前就把上一次的丢弃掉,注意这里并不是真正让这个网络请求取消了,本质上是没有办法取消掉的,

我只是让回来的结果丢弃掉而已不做任何处理了,那么就算是我点了n次其实我也只取了我最后一次的结果,所以这样看起来合情合理,但是对于网络流量要求的app来说就很不科学了

4 将2和3结合起来

首先我们做一个延时处理比如200ms,当达到延时处理后再发起请求,但是有个特殊地方比如我在下一个200ms内又发起请求,此时结果并没有回来,那么我们将之前的任务取消掉就好了,这样也就相对友好的

处理了这些矛盾,这里兼顾了2和3的优缺点

以下是我改进的代码,让任务可以手动取消

封装的超时Task类

  1 public class TimeoutTask
  2 {
  3     #region 字段
  4     private Action _action;
  5     private CancellationToken _token;
  6     private event AsyncCompletedEventHandler _asyncCompletedEvent;
  7     private TaskCompletionSource<AsyncCompletedEventArgs> _tcs;
  8     #endregion
  9
 10     #region 静态方法
 11     public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, CancellationToken token)
 12     {
 13         return await TimeoutTask.StartNewTask(action, token, Timeout.Infinite);
 14     }
 15
 16     public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, int timeout)
 17     {
 18         return await TimeoutTask.StartNewTask(action, CancellationToken.None, timeout);
 19     }
 20
 21     public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, CancellationToken token,
 22         int timeout = Timeout.Infinite)
 23     {
 24         var task = new TimeoutTask(action, token, timeout);
 25
 26         return await task.Run();
 27     }
 28     #endregion
 29
 30     #region 构造
 31
 32     public TimeoutTask(Action action, int timeout) : this(action, CancellationToken.None, timeout)
 33     {
 34
 35     }
 36
 37     public TimeoutTask(Action action, CancellationToken token) : this(action, token, Timeout.Infinite)
 38     {
 39
 40     }
 41
 42     public TimeoutTask(Action action, CancellationToken token, int timeout = Timeout.Infinite)
 43     {
 44         _action = action;
 45
 46         _tcs = new TaskCompletionSource<AsyncCompletedEventArgs>();
 47
 48         if (timeout != Timeout.Infinite)
 49         {
 50             var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
 51             cts.CancelAfter(timeout);
 52             _token = cts.Token;
 53         }
 54         else
 55         {
 56             _token = token;
 57         }
 58     }
 59     #endregion
 60
 61     #region 公用方法
 62
 63     /// <summary>
 64     /// 运行
 65     /// </summary>
 66     /// <returns></returns>
 67     public async Task<AsyncCompletedEventArgs> Run()
 68     {
 69         _asyncCompletedEvent += AsyncCompletedEventHandler;
 70
 71         try
 72         {
 73             using (_token.Register(() => _tcs.TrySetCanceled()))
 74             {
 75                 ExecuteAction();
 76                 return await _tcs.Task.ConfigureAwait(false);
 77             }
 78
 79         }
 80         finally
 81         {
 82             _asyncCompletedEvent -= AsyncCompletedEventHandler;
 83         }
 84
 85     }
 86
 87     public void Cancel()
 88     {
 89         if (!_token.CanBeCanceled)
 90         {
 91             _tcs.TrySetCanceled();
 92         }
 93     }
 94     #endregion
 95
 96     #region 私有方法
 97
 98     /// <summary>
 99     /// 执行Action
100     /// </summary>
101     private void ExecuteAction()
102     {
103         Task.Factory.StartNew(() =>
104         {
105             _action.Invoke();
106
107             OnAsyncCompleteEvent(null);
108         });
109     }
110
111     /// <summary>
112     /// 异步完成事件处理
113     /// </summary>
114     /// <param name="sender"></param>
115     /// <param name="e"></param>
116     private void AsyncCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
117     {
118         if (e.Cancelled)
119         {
120             _tcs.TrySetCanceled();
121         }
122         else if (e.Error != null)
123         {
124             _tcs.TrySetException(e.Error);
125         }
126         else
127         {
128             _tcs.TrySetResult(e);
129         }
130     }
131
132     /// <summary>
133     /// 触发异步完成事件
134     /// </summary>
135     /// <param name="userState"></param>
136     private void OnAsyncCompleteEvent(object userState)
137     {
138         if (_asyncCompletedEvent != null)
139         {
140             _asyncCompletedEvent(this, new AsyncCompletedEventArgs(error: null, cancelled: false, userState: userState));
141         }
142     }
143     #endregion
144 }
145
146 /// <summary>
147 /// 有返回值,可超时,可取消的Task
148 /// </summary>
149 /// <typeparam name="T"></typeparam>
150 public class TimeoutTask<T>
151 {
152     #region 字段
153     private Func<T> _func;
154     private CancellationToken _token;
155     private event AsyncCompletedEventHandler _asyncCompletedEvent;
156     private TaskCompletionSource<AsyncCompletedEventArgs> _tcs;
157     #endregion
158
159     #region 静态方法
160     public static async Task<T> StartNewTask(Func<T> func, CancellationToken token,
161         int timeout = Timeout.Infinite)
162     {
163         var task = new TimeoutTask<T>(func, token, timeout);
164
165         return await task.Run();
166     }
167
168     public static async Task<T> StartNewTask(Func<T> func, int timeout)
169     {
170         return await TimeoutTask<T>.StartNewTask(func, CancellationToken.None, timeout);
171     }
172
173     public static async Task<T> StartNewTask(Func<T> func, CancellationToken token)
174     {
175         return await TimeoutTask<T>.StartNewTask(func, token, Timeout.Infinite);
176     }
177
178
179
180     #endregion
181
182     #region 公用方法
183     /// <summary>
184     /// 运行Task
185     /// </summary>
186     /// <returns></returns>
187     public async Task<T> Run()
188     {
189         _asyncCompletedEvent += AsyncCompletedEventHandler;
190
191         try
192         {
193             using (_token.Register(() => _tcs.TrySetCanceled()))
194             {
195                 ExecuteFunc();
196                 var args = await _tcs.Task.ConfigureAwait(false);
197                 return (T)args.UserState;
198             }
199
200         }
201         finally
202         {
203             _asyncCompletedEvent -= AsyncCompletedEventHandler;
204         }
205
206     }
207
208
209     public bool CanBeCanceled
210     {
211         get { return _token.CanBeCanceled; }
212     }
213
214     public void Cancel()
215     {
216         if (!_token.CanBeCanceled)
217         {
218             _tcs.SetCanceled();
219         }
220     }
221     #endregion
222
223     #region 构造
224     public TimeoutTask(Func<T> func, CancellationToken token) : this(func, token, Timeout.Infinite)
225     {
226
227     }
228
229     public TimeoutTask(Func<T> func, int timeout = Timeout.Infinite) : this(func, CancellationToken.None, timeout)
230     {
231
232     }
233
234     public TimeoutTask(Func<T> func, CancellationToken token, int timeout = Timeout.Infinite)
235     {
236         _func = func;
237
238         _tcs = new TaskCompletionSource<AsyncCompletedEventArgs>();
239
240         if (timeout != Timeout.Infinite)
241         {
242             var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
243
244             cts.CancelAfter(timeout);
245             _token = cts.Token;
246         }
247         else
248         {
249             _token = token;
250         }
251     }
252     #endregion
253
254     #region 私有方法
255
256
257     /// <summary>
258     /// 执行
259     /// </summary>
260     private void ExecuteFunc()
261     {
262         ThreadPool.QueueUserWorkItem(s =>
263         {
264             var result = _func.Invoke();
265
266             OnAsyncCompleteEvent(result);
267         });
268     }
269
270     /// <summary>
271     /// 异步完成事件处理
272     /// </summary>
273     /// <param name="sender"></param>
274     /// <param name="e"></param>
275     private void AsyncCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
276     {
277         if (e.Cancelled)
278         {
279             _tcs.TrySetCanceled();
280         }
281         else if (e.Error != null)
282         {
283             _tcs.TrySetException(e.Error);
284         }
285         else
286         {
287             _tcs.TrySetResult(e);
288         }
289     }
290
291     /// <summary>
292     /// 触发异步完成事件
293     /// </summary>
294     /// <param name="userState"></param>
295     private void OnAsyncCompleteEvent(object userState)
296     {
297         if (_asyncCompletedEvent != null)
298         {
299             _asyncCompletedEvent(this, new AsyncCompletedEventArgs(error: null, cancelled: false, userState: userState));
300         }
301     }
302     #endregion
303 }

View Code

demo

 1 class Program
 2     {
 3         private static TimeoutTask<string> result;
 4
 5         static void Main(string[] args)
 6         {
 7
 8
 9             ThreadMethod();
10
11
12             Console.WriteLine("启动完成");
13             Console.ReadLine();
14         }
15
16         private async static void ThreadMethod()
17         {
18 //            await TimeoutTask.StartNewTask(LongTimeWork, 6000);
19 //            await TimeoutTask<string>.StartNewTask(LongTimeWork2, 2000);
20             try
21             {
22                 for (int i = 0; i < 5; i++)
23                 {
24
25                     //我手动取消掉上一次的
26                     if (result!=null)
27                     {
28                         try
29                         {
30                             //取消掉
31                             result.Cancel();
32                         }
33                         catch (Exception er)
34                         {
35                         }
36                     }
37
38                     result = new TimeoutTask<string>(LongTimeWork2);
39
40
41
42                     try
43                     {
44                         result.Run();
45                     }
46                     catch (Exception ee)
47                     {
48
49                     }
50                 }
51
52
53                 Console.WriteLine(result);
54             }
55             catch (Exception ex)
56             {
57
58             }
59         }
60
61         private static void LongTimeWork()
62         {
63             Thread.Sleep(5000);
64         }
65
66         private static string LongTimeWork2()
67         {
68             Thread.Sleep(5000);
69             return "XXD";
70         }
71
72
73     }

View Code

二 Task天生超时

什么是尝试超时,比如说连接数据库就有TryConnect尝试,在一些访问资源的时候经常用到,且Task本身也天生支持超时处理

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var task=Task.Factory.StartNew(() =>
{
Thread.Sleep(3 * 1000);

}, token);

var timeout = task.Wait(4*1000,token);

if (timeout)
{

}

Wait会等待给定的时间,如果在给定的时间内已经完成那么,将返回true,意思是在指定的时间内完成了一个task,反之就认为超时了,这个也不乏一种超时处理

转载于:https://www.cnblogs.com/rjjs/p/5588158.html

TPL异步并行编程之任务超时相关推荐

  1. PHP 异步并行编程_韩天峰

    2019独角兽企业重金招聘Python工程师标准>>> PHP 异步并行编程_韩天峰 韩天峰(Rango)多玩游戏平台技术负责人,swoole开源项目创始人.PHP的异步并行编程,介 ...

  2. android网络编程及网络超时处理

    android网络编程及网络超时处理 本文是收录的两篇关于这方面的文章 Android超时机制的处理 由于手机端应用的响应,与当时的无线通信网络状况有很大的关联.而通信网络往往具有不稳定,延迟长的特点 ...

  3. 网络编程中的超时检测

    http://blog.163.com/liukang_0404@126/blog/static/55682581201231955735693/ 我们在网络编程中常见的一种做法是:创建好套接字后以阻 ...

  4. 高并发编程-自定义带有超时功能的锁

    文章目录 概述 步骤 自定义超时异常处理类 ILock接口 实现类 测试 存在的问题 修复存在的问题 超时功能 测试超时功能 CustomLock 概述 我们知道synchronized的机制有一个很 ...

  5. php socket recv 超时,socket编程中的超时设置示例详解之一

    简介: 在网络通讯中,如果socket处于阻塞模式运行时,就需要考虑处理socket操作超时的问题. 所谓阻塞模式,是指其完成指定的操作之前阻塞当前的进程或线程,直到操作有结果返回. 在我们直接调用s ...

  6. 网络编程:网络超时检测(select poll setsockopt alarm)

    一.网络超时检测 1.1 概念 阻塞: 以读阻塞为例,如果缓冲区中有内容,则程序正常执行, 如果缓冲区没有内容,程序会一直阻塞,直到有内容,读取内容继续向下运行. 非阻塞: 以读阻塞为例,如果缓冲区中 ...

  7. python异步编程案例之超时

    asyncio.wait_for(aw,timeout,*,loop=None) timeout可以是None也可以是一个float或int类型的数字,表示需要等待的秒数.如果timeout是None ...

  8. C# 学习笔记——PL 并行编程 TPL 和传统 .NET 异步编程

    C# 学习笔记--PL 并行编程 TPL 和传统 .NET 异步编程 Task C# 多线程和异步模型 TPL模型 Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Fa ...

  9. 服务超时 — 基本原理

    web 编程中,超时通常分为客户端和服务端超时两种.我之所以要研究这个主题,是因为我自己遇到了一个有意思的服务端超时的问题.这也是本文我们将要重点讨论服务侧超时的原因. 先解释下基本术语:超时是一个时 ...

最新文章

  1. 从Java到Spring为何独得青睐Spring Summit 2017不可不知的那些事儿
  2. w ndows8怎么连接网络,(Wndows8.1优化设置全面解析.doc
  3. PHP将json或对象转成数组
  4. 你是否应该成为一名全栈工程师?
  5. iOS推送小结--swift语言
  6. php背景音乐合成,录音加背景音乐要怎么做 如何将两个音乐融合
  7. android 6.0 蓝牙进程,Android6.0-蓝牙权限问题
  8. Intellij IDEA中如何给main方法赋args
  9. 腾讯上海安全团队招聘实习生
  10. 基于C++的人机对弈的五子棋AI程序
  11. 格拉布斯准则异常数据_异常处理准则和最佳实践
  12. 【读书笔记】重新定义团队
  13. 测试模板:Showcase规范和流程
  14. 纯手工焊接七彩圣诞树
  15. 【SAP】 SAP自定义权限对象
  16. 2021年开源愿景大揭秘
  17. C++实现骰子涂色算法
  18. element更改导航菜单被选中项的背景颜色
  19. linux下生成ssh密钥并获取密钥
  20. 百度:良心何在?素质何在?道德何在?法律常识何在?人性何在?

热门文章

  1. Fastjson解析复杂json数据
  2. 清分、清算、结算的关系
  3. [4G5G专题-43]:物理层-4G/5G参考信号大全(DM-RS, PT-RS, CSI-RS, SRS)
  4. 科研踩坑:角度制三角函数求导要乘上π/180
  5. Leetcode286墙与门
  6. esxi显卡给2个虚拟机_利用ESXi实现一拖二和各系统独立运行——基础篇
  7. Mybatis——自定义映射ResultMap
  8. zed相机拆机_使用TX2+ZED相机运行ORBSLAM2和LearnVIORB
  9. mobl 针对移动Web开发的DSL(2)
  10. python数据分析常见错误_Python数据分析常用语句(一)