IT知识库 购物 网址 游戏 小说 歌词 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程 CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
站长资讯 .NET新手 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA VisualStudio ASP.NET-MVC .NET控件开发 EntityFramework WinRT-Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动 Html-Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP OracleERP DynamicsCRM K2 BPM 信息安全 企业信息 Android开发 iOS开发 WindowsPhone WindowsMobile 其他手机 敏捷开发 项目管理 软件工程 SQLServer Oracle MySQL NoSQL 其它数据库 Windows7 WindowsServer Linux
  IT知识库 -> .NET新手区 -> 多线程编程学习笔记——线程池(二) -> 正文阅读

[.NET新手区]多线程编程学习笔记——线程池(二)

多线程编程学习笔记——线程池(二) 接上文 多线程编程学习笔记——线程池(一)
三、线程池与并行度
此示例是学习如何应用线程池实现大量的操作,及与创建大量线程进行工作的区别。
1. 代码如下

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading; 

namespace ThreadPoolDemo
{  

    class Program
    {   

        static void Main(string[] args)
        {

            Console.WriteLine("开始测试线程池与自创线程。。。");
            const int total = 500;
            long millisecondes = 0;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            ThreadRun(total);
            sw.Stop();
            millisecondes = sw.ElapsedMilliseconds;
            decimal mom = (decimal)(Environment.WorkingSet / (1024 * 1024.0));            sw.Reset();

            sw.Start();
            ThreadPoolRun(total);

            sw.Stop();
            Console.WriteLine("自创线程总耗时 {0},占用内存:{1} MB", millisecondes,mom);
            Console.WriteLine("线程池总耗时 {0} ,占用内存:{1} MB", sw.ElapsedMilliseconds, Environment.WorkingSet / (1024 * 1024.0));
            Console.Read();

        }

        private static void  ThreadRun(int total)
        {
            using (var countdown = new CountdownEvent(total))
            {
                Console.WriteLine("开始--自创线程。。。");
                for (int i = 0; i < total; i++)
                {
                    var t = new Thread(() =>
                    {
                        Console.WriteLine("自创线程ID :{0}", Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        countdown.Signal();//向 CountdownEvent 注册信号,同时减小 CurrentCount 的值。

                    });
                    t.Start();
                }
                countdown.Wait();  // 阻塞当前线程,直到 CountdownEvent 的信号数量变为 0
                Console.WriteLine("-----------------");
            }
        }

        private static void ThreadPoolRun(int total)
        {
            using (var countdown = new CountdownEvent(total))

            {
                Console.WriteLine("开始--线程池。。。");
                for (int i = 0; i < total; i++)
                {
                    ThreadPool.QueueUserWorkItem(_ =>
                    {
                        Console.WriteLine("线程池工作线程ID :{0}", Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        countdown.Signal();//向 CountdownEvent 注册信号,同时减小 CurrentCount 的值。
                    });                 

                }
                countdown.Wait();  // 阻塞当前线程,直到 CountdownEvent 的信号数量变为 0
                Console.WriteLine("-----------------");

            }
        }
    }
}

 

2.程序运行结果如下图。
 

    1) 这个示例中我们自己创建了500个线程,每个线程一个操作,每个线程都阻塞100毫秒。总计耗时  11秒,消耗资源如下图。
 

    2)我们使用线程池执行相同的500个操作。总计耗时  9秒,消耗资源如下图。
 

从1)与2)的比较上可以看出来,自创线程消耗的CPU资源比线程池要多。
四、 从线程池中取消操作
如果我们要从线程池中取消某个线程的操作,应该如何实现呢?本示例使用CancellationTokenSource和CancellationToken两个类来实现在取消线程池中的操作。这两个是是在net 4.0引入的。
 1.示例代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading; 

namespace ThreadPoolDemo
{

    class Program
    {    

        static void Main(string[] args)
        {
            Console.WriteLine("开始测试线程池中取消正在运行的线程。。。");
            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOper(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();//取消线程操作
            }

            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();//取消线程操作

            }
            using (var cts = new CancellationTokenSource())

            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOper3(token));

                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();//取消线程操作
            }

            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine("。。。。。。。。。。取消正在运行的线程结束。。。。。。");
            Console.Read();
        }

        private static void  AsyncOperation(CancellationToken token)
        {

            try
            {
                Console.WriteLine("开始--线程池中的第二个工作线程。。。");
                for (int i = 0; i < 5; i++)

                {
                    token.ThrowIfCancellationRequested();//获取取消请求,抛出OperationCanceledException异常,
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }

                Console.WriteLine("-------线程池中的第二个工作线程 工作完成----------");
            }
            catch (OperationCanceledException ex)
            {
                Console.WriteLine("使用抛出异常方法取消第二个工作线程  ID:{0},{1}", Thread.CurrentThread.ManagedThreadId,ex.Message);
            }
        }
        private static void AsyncOper(CancellationToken token)
        {

            Console.WriteLine("开始--线程池中的第一个工作线程。。。");
            for (int i = 0; i < 5; i++)
            {
                if (token.IsCancellationRequested)//判断是否已经取消操作
                {
                    Console.WriteLine("使用轮询方法取消工作线程  ID:{0}", Thread.CurrentThread.ManagedThreadId);
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("-------线程池中的第一个工作线程 工作完成----------");
        }
        private static void AsyncOper3(CancellationToken token)
        {
            Console.WriteLine("开始--线程池中的第三个工作线程。。。");
            bool cancel = false;
            token.Register(()=>cancel = true);
            for (int i = 0; i < 5; i++)
            {
                if (cancel)//判断是否已经取消操作
                {
                    Console.WriteLine("通过注册回调函数取消第三个工作线程  ID:{0}", Thread.CurrentThread.ManagedThreadId);
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }   

            Console.WriteLine("-------线程池中的第三个工作线程 工作完成----------");
        }
    }
}

2.运行结果如下图。
 

本示例一共实现了三种取消线程池中操作的方式。
轮询检查CancellationToken.IsCancellationRequested属性,如果为true,则说明操作被取消。 抛出一个OperationCancellationException异常。这允许操作之外的代码来取消操作。 注册一个回调函数,当操作取消时,线程池将调用回调函数,这样做的好处是将取消操作逻辑传递到另一个异步操作中。
上一篇文章           查看所有文章
加:2017-11-13 23:21:21  更:2017-11-13 23:21:23 
 
  .NET新手区 最新文章
将ZIP文件添加到程序集资源文件然后在运行时
Web服务的调用
.NET创建WebService服务简单的例子
多线程编程学习笔记——任务并行库(三)
序列化和反序列化
Spring学习之路
cs代码实现控件移动TranslateTransform
Asp.net基础知识
ACdream原创群赛(11)の风神日华神专场C.神奇
SQL 存储和触发器
技术频道: 站长资讯 .NET新手区 ASP.NET C# WinForm Silverlight WCF CLR WPF XNA Visual Studio ASP.NET MVC .NET控件开发 Entity Framework WinRT/Metro Java C++ PHP Delphi Python Ruby C语言 Erlang Go Swift Scala R语言 Verilog 其它语言 架构设计 面向对象 设计模式 领域驱动设计 Html/Css JavaScript jQuery HTML5 SharePoint GIS技术 SAP Oracle ERP Dynamics CRM K2 BPM 信息安全 企业信息化其他 Android开发 iOS开发 Windows Phone Windows Mobile 其他手机开发 敏捷开发 项目与团队管理 软件工程其他 SQL Server Oracle MySQL NoSQL 其它数据库 Windows 7 Windows Server Linux
脚本语言: vbs/VBScript DOS/BAT hta htc python perl 游戏相关 VBA 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 其它教程
网站开发: CSS/HTML/Xhtml html5 CSS XML/XSLT Dreamweaver教程 经验交流 开发者乐园 Android开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 新闻资讯 小游戏 Chinese Culture 股票 三丰软件 开发 中国文化 网文精选 阅读网 看图 日历 万年历 2018年10日历
2018-10-24 3:19:12
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库