http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 8908|回复: 3

[性能] .NET:如何让线程支持超时?

[复制链接]
发表于 2015-5-6 16:48:49 | 显示全部楼层 |阅读模式
.NET:如何让线程支持超时?

MS 现在不推荐使用低级别的 Thread 编程,而推荐使用 Task.
如何让线程支持超时?   下面介绍三种方法
方法一:使用 CancellationTokenSource(需要.net framework 4.5)
方法二:使用 Join
方法三:基于 Task 的实现


方法一:使用 CancellationTokenSource
private static void TimeoutTest1()
        {
            var cts = new CancellationTokenSource();

            var thread = new Thread(() =>
            {
                Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
                Thread.Sleep(10000);
                Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
            });

            cts.Token.Register(() =>
            {
                thread.Abort();
            });
            cts.CancelAfter(1000);

            thread.Start();
            thread.Join();

            Console.WriteLine(String.Format("线程{0}的状态:{1}", thread.ManagedThreadId, thread.ThreadState));
        }

输出



备注
这里采用了 Abort 终止了线程,CancellationTokenSource 也支持其它模式,可以去官方看看文档。
方法二:使用 Join

private static void TimeoutTest2()
        {
            var thread = new Thread(() =>
            {
                Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
                Thread.Sleep(10000);
                Console.WriteLine(String.Format("线程{0}执行中", Thread.CurrentThread.ManagedThreadId));
            });

            thread.Start();
            thread.Join(1000);
            thread.Abort();

            Console.WriteLine(String.Format("线程{0}的状态:{1}", thread.ManagedThreadId, thread.ThreadState));
        }
输出




方法三:基于 Task 的实现
private static void TimeoutTest3()
        {
            var cts = new CancellationTokenSource();
            var task = new Task(() =>
            {
                while (true)
                {
                    cts.Token.ThrowIfCancellationRequested();

                    Console.WriteLine("xxxxxx");
                    Thread.Sleep(1000);
                }
            }, cts.Token);

            task.Start();

            cts.CancelAfter(5000);

            Console.ReadLine();
        }
输出



如何让线程在执行结束后销毁?
线程执行完、遇到未处理异常和被终止后就自动不可用了,如果是垃圾,自然会被 GC 给回收,有一点需要说明的是:线程的未处理异常会导致应用程序的终止,一个线程的异常不会自动冒泡到其它线程。
备注
我学习多线程知识感觉到的一个好处就是:让我对数据库并发有了更深刻的认识了,找个机会写写线程的乐观锁和数据库的乐观锁的比较,思路基本一样。


框架地址:http://happy.codeplex.com


原文来自:http://www.cnblogs.com/happyframework/p/3440877.html;

BeginInvoke、ThreadPool、Task三类异步方法的区别和速度比较

速度(最快为1
返回值
多参数
等待在时限内完成
超时后结束
ThreadPool.UnsafeQueueUserWorkItem()
1
非原生支持1
非原生支持
非原生支持3
不支持
ThreadPool.QueueUserWorkItem()
2.7
非原生支持1
非原生支持
非原生支持3
不支持
Task()
4.5
支持2
非原生支持
支持
自愿结束
Delegate.BeinInvoke()
25.4
非原生支持1
支持
支持4
不支持
Thread.Start()
11009
非原生支持1
非原生支持
非原生支持3
支持


  • 如ThreadPool.UnsafeQueueUserWorkItem(()=>result=Add(1,2));
  • 用Task<>
  • 里面在程序末尾EventWaitHandle.Set(),外面WaitOne(TimeSpan)。
  • 获得BeginInvoke的返回值asyncResult,再调asyncResult.AsyncWaitHandle.WaitOne();
  • 有图有真相。这是各种异步方法循环调用N次所需的时间。





注意,上面BeginInvoke的用法并不完整,应当再调用EndInvoke。但是鉴于BeginInvoke已经最慢了,EndInvoke便不加了。
所以,如果无需返回值,一般就用ThreadPool吧,要更多控制,就Task。鄙人想不到用BeginInvoke的时机。

参考
代码:  
   static void Main(string[] args)
        {
            Action threadStart = (() => { });
            WaitCallback waitCallback = new WaitCallback(a => { });
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 0; i < 10000; i++)
            {
                System.Threading.ThreadPool.UnsafeQueueUserWorkItem(waitCallback, null);
            }
            stopWatch.Stop();
            Console.WriteLine("{0,-40}{1}", "ThreadPool.UnsafeQueueUserWorkItem():", stopWatch.ElapsedTicks);
            GC.Collect();

            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 0; i < 10000; i++)
            {
                System.Threading.ThreadPool.QueueUserWorkItem(waitCallback);
            }
            stopWatch.Stop();
            Console.WriteLine("{0,-40}{1}", "ThreadPool.QueueUserWorkItem():", stopWatch.ElapsedTicks);
            GC.Collect();

            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 0; i < 10000; i++)
            {
                Task t = new Task(threadStart);
                t.Start();
            }
            stopWatch.Stop();
            Console.WriteLine("{0,-40}{1}", "Task():", stopWatch.ElapsedTicks);
            GC.Collect();

            stopWatch.Reset();
            stopWatch.Start();
            for (int i = 0; i < 10000; i++)
            {
                threadStart.BeginInvoke(null, null);
            }
            stopWatch.Stop();
            Console.WriteLine("{0,-40}{1}", "Delegate.BeinInvoke():", stopWatch.ElapsedTicks);

        }







1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
 楼主| 发表于 2015-5-6 16:54:23 | 显示全部楼层
抢沙发!
回复

使用道具 举报

 楼主| 发表于 2015-5-6 16:57:03 | 显示全部楼层
抢板凳
回复

使用道具 举报

发表于 2016-4-25 21:34:56 | 显示全部楼层
图片看不了啊亲
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-5-6 14:58

© 2014-2021

快速回复 返回顶部 返回列表