标签:com 入口 ati log div 传递参数 sys tar 建立
多线程简单来说就是让计算机进行“一心多用”,不过此处一心多用并不是真正的一心多用,只是在不同的时间片段(极短的时间片段内)分别执行不同的操作,但在单位时间片段内饰一心一用。简单举个例子,周伯通让小龙女学习左右互搏,让她一手画方一手画圆,做到一心两用。那我们来简单分析一下,如果不是同时结束呢,我们先这样来,左手先画四分之一圆,完成后右手再画正方形的一条边,然后依次类推,知道方圆均画完。这样属于两个手分别操作,那么我们进一步细分,左后先画八分之一圆,右手再画八分之一正方形,当然这样还是两个手分别操作,那么我们整个圆和方形分成一百步画完呢,假如分成一千步呢?分成一千步即使每一步都是单独的在画圆或者或方,但是总体上方圆基本同时在进行。这就是多线程所展现给我们的,但是多线程的意义就是当某一线程阻塞了,不会导致整个程序等待。加入我们只会用一只手画方圆,先画圆后画方,那么在画圆的过程中加入手抽筋了,那我们都要在等待手恢复,如果一手画方一手画圆,那么左手即使抽筋了,只是影响画圆而不影响右手画方。这就是多线程的意义。下面讲解三种最基本的开启线程方法,讲解过程中为了分别讲解,只引用了部分代码,最后会给出完整代码,建议可以边运行边看分步讲解。
1、引入命名空间System.Threading,最基本在简洁的方法ThreadStart/ParameterizedThreadStart,前者不带参数,后者可以给方法传递一个参数(带参数的方法入口参数必须为object类型),但是最基本的方法,开启线程比较随意,容易混乱而且开启过多线程也会影响性能。开启线程不过是在主程序运行或者其他方法运行时,开启其他方法,既然开启其他就必然用得到委托,本质上还是向thread类中传递要开启的方法,具体开启线程有thread类完成。开启线程方法:
(一)定要开启的方法
static void AsyncDemo()//无参数的方法 { for(int i=0;i<=10;i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } } static void AsyncDemo(object obj)//有参数的方法 { string _obj = (string)obj; Console.WriteLine(_obj); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } }
(二)开启线程
//Thread thread = new Thread(new ThreadStart(AsyncDemo)); //thread.Start(); string para = "Hello World!"; Thread thread = new Thread(new ParameterizedThreadStart(AsyncDemo)); thread.Start(para);
(三)主程序的运行
//主程序 for (int i=0;i<=10;i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); }
本例子通过两个for语句来分别假定主程序方法和线程方法,如果不用线程,会一个循环执行完在执行另一个循环,如果没有Thread.Sleep(100)则体现不出同时运行的效果,因为就是在极短的时间片段内,每一个循环都可以执行完,所以为了达到效果,让每一个都暂停0.1s。
2、在程序中随意开启线程会影响程序的质量,所以C#提供了线程池来管理线程,即通过QueueUserWorkItem来开启线程,他有两个重载,可以传递参数给开启线程的方法。开启线程的方法还是采用1、中方法,线程开启如下:
string str = "Hello World!"; ThreadPool.SetMaxThreads(1000, 1000);//定义处于活动状态的线程池的请求数目 ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncDemo),str); // ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncDemo));//无参数的方法
3、以上两种方法都没有返回值,若一个方法有返回值,则需要其他方法来实现。开启线程本质上还是通过委托传递一个方法(函数),而委托也为我们提供了相应开启线程的方法。当我们定义好委托以后,在码代码的时候平台会自动给我们提示它可能存在的方法,其中BeginInvoke(name, null, null)方法就是来开启线程,第一个参数为方法所需要的入口参数,第二个为回调函数,其参数必须为一个IAsyncResult 接口,第三个为 为回调函数传入的参数。后两个参数可以为空,它返回一个IAsyncResult类型的接口,通过此接口传入EndInvoke(result)方法即可获取返回值。下面为具体步骤:
(一)建立委托
public delegate string Mydeletegate(string str);
(二)定义相关方法
static string AsyncDemo(string obj) { string _obj = (string)obj; Console.WriteLine(_obj); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } return "Hello " + obj; }
(三)委托指向方法并开启线程
IAsyncResult result = de.BeginInvoke(name, null, null); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); } string redata = de.EndInvoke(result); Console.WriteLine(redata);
但是此方法会存在一个问题,即如果把上述代码中的redata那一语句放在for循环之前,则会先执行型委托指向的方法的循环,后执行主程序(可以自行测试),因为主程序在等待执行完redata=。。。。后再执行for语句,所以可以充分利用接口IAsyncResult提供的方法或者字段。也可以采用BeginInvoke方法的第二个参数,回调函数,即把EndInvoke方法放入回调函数中,本例的回调函数为Completed。回调函数如下:
static void Completed(IAsyncResult res) { string str = (string)res.AsyncState; AsyncResult _res = (AsyncResult)res; Mydeletegate de1 = (Mydeletegate)_res.AsyncDelegate; string data = de1.EndInvoke(res); Console.WriteLine(data); Console.WriteLine(str); }
对相关参数进行一下解释:通过接口中的AsyncState可以获取异步操作传入的信息,即BeginInvoke的第三个参数,为object类型的,要转化成所用的类型。我们要在此函数中完成EndInvoke就需要获取BeginInvoke的委托,查看元数据可以知道AsyncResult 继承了IAsyncResult 接口,AsyncResult中的AsyncDelegate属性可以获取相关委托,所以先把传入的IAsyncResult 转化为AsyncResult 类型,在通过AsyncDelegate获取到委托(其为object类型,需要转化为委托类型),然后调用EndInvoke方法,获取返回值, 主程序如下:
de.BeginInvoke(name, new AsyncCallback(Completed), index); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); }
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
在最后附上三种方法的完整程序,这三种方法为最基本的方法,在以后不管是网络请求还是文件I/O的异步编程都与委托类方法一样。
方法1的完整代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace MyThread { class Program { static void AsyncDemo()//无参数的方法 { for(int i=0;i<=10;i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } } static void AsyncDemo(object obj)//有参数的方法 { string _obj = (string)obj; Console.WriteLine(_obj); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } } static void Main(string[] args) { //无参数方法 //Thread thread = new Thread(new ThreadStart(AsyncDemo)); //thread.Start(); string para = "Hello World!"; Thread thread = new Thread(new ParameterizedThreadStart(AsyncDemo)); thread.Start(para); //主程序 for (int i=0;i<=10;i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); } Console.ReadKey(); } } }
方法2的完整代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ThreadPoolTest { class Program { static void AsyncDemo() { for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } } static void AsyncDemo(object obj) { string _obj = (string)obj; Console.WriteLine(_obj); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } } static void Main(string[] args) { string str = "Hello World!"; ThreadPool.SetMaxThreads(1000, 1000);//定义处于活动状态的线程池的请求数目 ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncDemo),str); // ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncDemo));//无参数的方法 for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); } Console.ReadKey(); } } }
方法3的完整代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Runtime.Remoting.Messaging; namespace Deletegatetest { public delegate string Mydeletegate(string str); class Program { static string AsyncDemo(string obj) { string _obj = (string)obj; Console.WriteLine(_obj); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Async thread : " + i); } return "Hello " + obj; } //回调函数 static void Completed(IAsyncResult res) { string str = (string)res.AsyncState; AsyncResult _res = (AsyncResult)res; Mydeletegate de1 = (Mydeletegate)_res.AsyncDelegate; string data = de1.EndInvoke(res); Console.WriteLine(data); Console.WriteLine(str); } static void Main(string[] args) { string name = "Andy"; string index = "Index!"; Mydeletegate de = new Mydeletegate(AsyncDemo); //IAsyncResult result = de.BeginInvoke(name, null, null); de.BeginInvoke(name, new AsyncCallback(Completed), index); for (int i = 0; i <= 10; i++) { Thread.Sleep(100); Console.WriteLine("Main thread : " + i); } //string redata = de.EndInvoke(result); //Console.WriteLine(redata); //for (int i = 0; i <= 10; i++) //{ // Thread.Sleep(100); // Console.WriteLine("Main thread : " + i); //} Console.ReadKey(); } } }
标签:com 入口 ati log div 传递参数 sys tar 建立
原文地址:http://www.cnblogs.com/llstart-new0201/p/6860733.html