三沣开发知识 购物 网址 游戏 小说 歌词 地图 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 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知识库 -> C# -> 线程系列04,传递数据给线程,线程命名,线程异常处理,线程池 -> 正文阅读
 

[C#]线程系列04,传递数据给线程,线程命名,线程异常处理,线程池

线程系列04,传递数据给线程,线程命名,线程异常处理,线程池 本篇体验:如何传递数据给线程,如何给线程命名,线程的异常处理,线程池。实在是太基础的部分。
□ 传递数据给线程
※ 使用Lambda表达式

    class Program


    {


        static void Main(string[] args)


        {


            Thread t = new Thread(() => Say("hello", "world"));


            t.Start();


        }


        static void Say(string msg, string msg1)


        {


            Console.WriteLine("第一个参数值是:"+msg);


            Console.WriteLine("第二个参数值是:" + msg1);


        }


    }


使用Lambda表达式需要注意的一个问题。

    class Program


    {


        static void Main(string[] args)


        {


            for (int i = 0; i < 10; i++)


            {


                new Thread(() => Console.WriteLine("当前线程#" + Thread.CurrentThread.ManagedThreadId + "输出的值是:" + i)).Start();


            }


        }


    }


说明,有些线程共享了局部变量i。如何解决线程共享栈变量的问题呢?只需要在每次遍历循环的时候,把i赋值给一个临时变量,再打印临时变量,不直接打印栈变量i。

    class Program


    {


        static void Main(string[] args)


        {


            for (int i = 0; i < 10; i++)


            {


                int temp = i;


                new Thread(() => Console.WriteLine("当前线程#" + Thread.CurrentThread.ManagedThreadId + "输出的值是:" + temp)).Start();


            }


        }


    }


打印的值没有重复的。
※ 使用线程的实例方法Start

    class Program


    {


        static void Main(string[] args)


        {


            Thread t = new Thread(Say);


            t.Start("hello");


        }


        static void Say(object msg)


        {


            string str = (string) msg;


            Console.WriteLine(str);


        }


    }

之所以可以这样做,是因为Thread的构造函数可以接收2种类型的形参。

public delegate void ThreadStart();


public delegate void ParameterizedThreadStart (object obj);

所有符合ParameterizedThreadStart这个委托定义的方法,必须有一个object类型的参数,然后在实例方法Start中传递参数。使用这种方式传递参数的弊端是:
1、只能传递一个参数
2、在方法体中,每次都要对object类型进行转换,拆箱
□ 给线程命名

    class Program


    {


        static void Main(string[] args)


        {


            Thread.CurrentThread.Name = "主线程";


            Thread t = new Thread(Say);


            t.Name = "其它工作线程";


            t.Start();


            Say();


        }


        static void Say()


        {


            Console.WriteLine("我的名字是:" + Thread.CurrentThread.Name);


        }


    }

通过Name属性可以设置或获取当前线程和实例线程的名称。
□ 线程的异常处理
一个线程无法捕获另外线程的异常。

    class Program


    {


        static void Main(string[] args)


        {


            try


            {


                new Thread(Say).Start();


            }


            catch (Exception)


            {


                Console.WriteLine("有异常");


            }


        }


        static void Say()


        {


            throw null;


        }


    }


以上,在主线程的catch语句块中,无法捕获另外一个线程的异常。
实际上,一个线程的异常必须在该线程方法内捕获。

    class Program


    {


        static void Main(string[] args)


        {


            new Thread(Say).Start();


        }


        static void Say()


        {


            try


            {


                throw null;


            }


            catch (Exception)


            {


                Console.WriteLine("捕获到异常了");


            }


        }


    }


□ 线程池
当创建一个线程,会用几十到几百毫秒的时间创建该线程的栈,而且,在默认情况下,每个线程需要1M的栈空间。线程池做到了共享和重复使用线程,性能得以提高。线程池还可以设置允许的最多线程数,一旦达到这个极限值,多余的线程需要排队,等待线程池中的线程执行结束再进入。
线程池的默认的最大线程数因计算机不同而异。在.NET 4.0及其以后的版本中,在2位计算机最大线程数为1023个,64位为32768;在.NET3.5中,线程池最大线程数是250个;在.NET2.0中,线程池最大线程数为25个。当然,可以通过TreadPool.SetMaxThreads来设置线程池的最大线程数,也可以通过ThreadPool.SetMinThreads来设置最小线程数。
线程池中线程的IsBackground属性默认为true。这意味着:主线程结束,应用程序结束,所有线程池中的后台线程结束。
※ 通过TPL进入线程池
TPL,Task Parallel Library,是一个处理并行任务的一个类库。

    class Program


    {


        static void Main(string[] args)


        {


            Task tast = Task.Factory.StartNew(Say);


            tast.Wait();


        }


        static void Say()


        {


            Console.WriteLine("hello,我已经是线程池中的线程了");


        }


    }


使用System.Net.WebClient的实例方法DownloadString方法下载某个网页,使用泛型Task<T>来处理。

    class Program


    {


        static void Main(string[] args)


        {


            Task<string> task = Task.Factory.StartNew<string>(() => DownloadString("http://www.baidu.com"));


            Console.WriteLine("Task在工作呢,我玩会啊~~");


            Console.WriteLine("Task在工作呢,我玩会啊~~");


            Console.WriteLine("Task在工作呢,我玩会啊~~");


            string result = task.Result;


            Console.WriteLine(result);


        }


        static string DownloadString(string uri)


        {


            using (var wc = new System.Net.WebClient())


            {


                return wc.DownloadString(uri);


            }


        }


    }

※ 不通过TPL进入线程池

    class Program


    {


        static void Main(string[] args)


        {


            ThreadPool.QueueUserWorkItem(Say);


            ThreadPool.QueueUserWorkItem(Say, 123);


            Console.ReadLine();


        }


        static void Say(object data)


        {


            Console.WriteLine("我来自线程池,我获取到的数据是:" + data);


        }


    }

  
※ 使用委托进入线程池

    class Program


    {


        static void Main(string[] args)


        {


            Func<string, int> method = GetLength;


            IAsyncResult ia = method.BeginInvoke("test", null, null);


            Console.WriteLine("线程池的线程在工作者呢,我先玩会~");


            int result = method.EndInvoke(ia);


            Console.WriteLine("test的长度为:" + result);


        }


        static int GetLength(string s)


        {


            return s.Length;


        }


    }


把方法赋值给委托变量,CLR会创建一个线程池中的线程。
线程系列包括:
线程系列01,前台线程,后台线程,线程同步 线程系列02,多个线程同时处理一个耗时较长的任务以节省时间 线程系列03,多线程共享数据,多线程不共享数据
线程系列04,传递数据给线程,线程命名,线程异常处理,线程池 线程系列05,手动结束线程 线程系列06,通过CLR代码查看线程池及其线程 线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
线程系列09,线程的等待、通知,以及手动控制线程数量
线程系列10,无需显式调用线程的情形
参考资料:http://www.albahari.com/threading
  C# 最新文章
字符串阵列分别输出元素的索引,原值和长度
格式化你的字符串
C#宣告一个变量
C#中级
拆分一个字符串并把每个字符单独输出
通过手机号定位归属地
.NET轻量级ORM框架Dapper修炼手册
windows服务安装及卸载
(3)MEF插件系统中通信机制的设计和实现
Task.FromResult应用场景举例
上一篇文章      下一篇文章      查看所有文章
加:2015-03-29 22:43:36  更:2017-05-14 17:05:33 
 
技术频道: 站长资讯 .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年7日历
2018-7-22 22:39:55
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT知识库