目录
线程开启方式(一)-异步委托
创建线程的一种简单方式是定义一个委托,并异步调用它。 委托是方法的类型安全的引用。Delegate类 还支持异步地调用方法。在后台,Delegate类会创建一个执行任务的线程。
class Program
{
static int Test(int i, string str)
{
Console.WriteLine("test" + i + str);
Thread.Sleep(100);//让当前线程休眠(暂停线程的执行) 单位ms
return 200;
}
static void Main(string[] args)
{
//在main线程中执行 一个线程里面语句的执行 是从上到下的
//1,通过委托 开启一个线程
Func<int, string, int> a = Test;
IAsyncResult ar = a.BeginInvoke(30, "siki", null, null);// 开启一个新的线程去执行 a所引用的方法
//IAsyncResult 可以取得当前线程的状态
//可以认为线程是同时执行的(异步执行)
Console.WriteLine("main");
while (ar.IsCompleted == false)//如果当前线程没有执行完毕
{
Console.Write(".");
Thread.Sleep(10); //控制子线程的检测频率
}
int res = a.EndInvoke(ar);//取得异步线程的返回值
Console.WriteLine(res);
Console .ReadKey ();
}
}
线程开启方式(二)-Thread类
我们构造一个thread对象的时候,可以传递一个静态方法,也可以传递一个对象的普通方法。
使用Thread类可以创建和控制线程。Thread构造函数的参数是一个无参无返回值的委托类型。
在这里哪个先输出是无法保证了线程的执行有操作系统决定,只能知道Main线程和分支线程是同步执行的。在这里给Thread传递一个方法,调用Thread的Start方法,就会开启一个线程去执行,传递的方法。
给线程传递一些数据可以采用两种方式,一种方式是使用带ParameterizedThreadStart委托参数的Thread构造函数,一种方式是创建一个自定义的类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,之后启动线程。
1)传递静态方法
class Program
{
static void DownloadFile()
{
Console.WriteLine("开始下载:"+Thread .CurrentThread .ManagedThreadId );
//Thread .CurrentThread .ManagedThreadId 当前线程id
Thread.Sleep(2000);
Console.WriteLine("下载完成");
}
static void Main(string[] args)
{
Thread t = new Thread(DownloadFile);//创建出来Thread对象,这个线程并没有启动
t.Start();//开始,开始去执行线程
Console.WriteLine("Main");
Console.ReadKey();
}
}
还可以传递参数,方式1:
class Program
{
static void DownloadFile(object fileName)
{
Console.WriteLine("开始下载:" +fileName );
Thread.Sleep(2000);
Console.WriteLine("下载完成");
}
static void Main(string[] args)
{
Thread t = new Thread(DownloadFile);//创建出来Thread对象,这个线程并没有启动
t.Start("种子");//开始去执行线程
Console.WriteLine("下载中...");
Console.ReadKey();
}
}
2)传递一个对象的普通方法
class MyThread
{
private string filename;
private string filepath;
public MyThread(string fileName, string filePath)
{
this.filename = fileName;
this.filepath = filePath;
}
public void DownFile()
{
Console.WriteLine("开始下载" + filename + filepath);
Thread.Sleep(2000);
Console.WriteLine("下载完成");
}
}
class Program
{
static void DownloadFile(object fileName)
{
Console.WriteLine("开始下载:" +fileName );
Thread.Sleep(2000);
Console.WriteLine("下载完成");
}
static void Main(string[] args)
{
MyThread my = new MyThread("种子", "http://www.xxx.bbs");
Thread t = new Thread(my.DownFile);
t.Start();
Console.ReadKey();
}
}
3)通过lambda表达式(委托参数的地方都可以使用Lambda表达式)
class Program
{
static void Main(string[] args)
{
//Thread t = new Thread(DownloadFile);//创建出来Thread对象,这个线程并没有启动
Thread t = new Thread(() =>
{
Console.WriteLine("开始下载:" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
Console.WriteLine("下载完成");
});
t.Start();//开始,开始去执行线程
Console.WriteLine("Main");
Console.ReadKey();
}
}
线程开启方式(三)-线程池
创建线程需要时间。 如果有不同的小任务要完成,就可以事先创建许多线程 , 在应完成这些任务时发出请求。 这个线程数最好在需要更多的线程时增加,在需要释放资源时减少。
不需要 自己创建线程池,系统已经有一个ThreadPool类管理线程。 这个类会在需要时增减池中线程的线程数,直到达到最大的线程数。 池中的最大线程数是可配置的。 在双核 CPU中 ,默认设置为1023个工作线程和 1000个 I/o线程。也可以指定在创建线程池时应立即启动的最小线程数,以及线程池中可用的最大线程数。 如果有更多的作业要处理,线程池中线程的个数也到了极限,最新的作业就要排队,且必须等待线程完成其任务。
class Program
{
static void DownloadFile(object fileName)
{
Console.WriteLine("线程开始:"+Thread .CurrentThread .ManagedThreadId );
Thread.Sleep(2000);
Console.WriteLine("线程结束");
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(DownloadFile);
ThreadPool.QueueUserWorkItem(DownloadFile);
ThreadPool.QueueUserWorkItem(DownloadFile);
ThreadPool.QueueUserWorkItem(DownloadFile);
ThreadPool.QueueUserWorkItem(DownloadFile);
Console.ReadKey();
}
}
线程开启方式(四)-任务
class Program
{
static void ThreadMethod()
{
Console.WriteLine("任务开始:");
Thread.Sleep(2000);
Console.WriteLine("任务结束");
}
static void Main(string[] args)
{
//Task t = new Task(ThreadMethod);
//t.Start();也可以
TaskFactory tf = new TaskFactory();
tf.StartNew(ThreadMethod);
Console.WriteLine("main");
Console.ReadKey();
}
}