本章我们接着主要是对多线程进行续讲(接上一章),主讲线程池和任务(Task)
- 线程池作用
创建线程需要一定的时间,为了提高效率可以事先创建一些线程
- 创建线程池的方法
系统有一个 ThreadPool类,去管理线程。最大线程数量是可以配置的,最大线程可达到1023个工作线程,1000个IO线程
- 线程特性
特性1:线程池创建的线程都是后台线程,不能把线程池中线程改为前台线程,也不能修改线程池中优先级与名称
特性2:线程池中的线程只能用于时间比较短的任务(如果后台线程需要长时间运行,则需要单独开启,不适合用线程池)
private void ThreadMethod1(object para)
{
Console.WriteLine("开始下载(当前线程编号):"+Thread.CurrentThread.ManagedThreadId); //模拟迅雷下载例子
Thread.Sleep(3000);
Console.WriteLine("下载完毕");
}//学习“线程池”
public void Test1()
{
//使用线程
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);Console.ReadLine(); //因为线程池开的线程默认是后台线程,所以必须加这一句
}
- 任务Task
ThreadPool.QueueUserWorkItem()这个技术存在许多限制。其中最大的问题是没有一个内建的机制让你知道什么时候操作完成,也没有一个机制在操作完成时获取一个返回值,这些问题使得我们都不敢启用这个技术
Task特性:可以指定在(一个)任务完成之后,应开始运行之后另一个特性任务。例如:一个使用前一个任务结果的新任务,如果前一个任务失败了,这个任务就应该执行一些清理工作
连续任务:如果一个任务的完成,是需要其他任务的完成为前提条件的,则称之为 连续任务,如下:
* Task t1=new Task(Thread1);
* Task t2=t1.ContinueWith(Thread2); //t2就是依赖t1的
* Task t3=t1.ContinueWith(Thread3);//t3就是依赖t1的
* 本技术为我们提供了执行任务的先后顺序
任务的层次结构:在一个任务中,又启动一个新任务,相当于新的任务是本任务的子任务。两个任务异步执行,如果父任务执行完了,子任务未执行完,它的状态会被设置为WaitingForChildrenToComplete,只有子任务也执行完毕了,父任务的状态才变为RunToCompletion
任务与线程的区别:
* 1:任务是线程的封装
* 2:任务有“父子”关系,线程没有
public void ThreadMethod2()
{
Console.WriteLine("开始 下载");
Thread.Sleep(2000);
Console.WriteLine("下载完毕");
}//学习“任务”
public void Test2()
{
Task task = new Task(ThreadMethod2);
task.Start();
Console.ReadLine(); //Task也是后台线程,所以也需要加这一行,不然不执行
}//介绍“任务工厂”
public void Test3()
{
TaskFactory tf = new TaskFactory();
Task task = tf.StartNew(ThreadMethod2);Console.ReadLine();
}
完整代码如下:
/***************
*
* Title:
*
* Description:
* 功能:学习线程池
* 线程池的作用:创建线程需要一定的时间,为了提高效率可以事先创建一些线程
* 创建线程池的方法:系统有一个 ThreadPool类,去管理线程。最大线程数量是可以配置的,最大线程可达到1023个工作线程,1000个IO线程
* 特性1:线程池创建的线程都是后台线程,不能把线程池中线程改为前台线程,也不能修改线程池中优先级与名称
* 特性2:线程池中的线程只能用于时间比较短的任务(如果后台线程需要长时间运行,则需要单独开启,不适合用线程池)
*
*
* 功能:学习“任务Task”
* 区别:Task和ThreadPool.QueueUserWorkItem的区别是,ThreadPool.QueueUserWorkItem()这个技术存在许多限制。其中最大的问题是没有一个内建的机制让你知道什么时候操作完成,
* 也没有一个机制在操作完成时获取一个返回值,这些问题使得我们都不敢启用这个技术
*
* Task特性:可以指定在(一个)任务完成之后,应开始运行之后另一个特性任务。例如:一个使用前一个任务结果的新任务,如果前一个任务失败了,这个任务就应该执行一些清理工作
*
* 连续任务:如果一个任务的完成,是需要其他任务的完成为前提条件的,则称之为 连续任务,如下:
* Task t1=new Task(Thread1);
* Task t2=t1.ContinueWith(Thread2); //t2就是依赖t1的
* Task t3=t1.ContinueWith(Thread3);//t3就是依赖t1的
* 本技术为我们提供了执行任务的先后顺序
*
* 任务的层次结构:在一个任务中,又启动一个新任务,相当于新的任务是本任务的子任务。两个任务异步执行,如果父任务执行完了,子任务未执行完,它的状态会被设置为WaitingForChildrenToComplete,只有子任务也执行完毕了,父任务的状态才变为RunToCompletion
*
* 任务与线程的区别:
* 1:任务是线程的封装
* 2:任务有“父子”关系,线程没有
*
*
* Author:王亚东
*
* Date:2024
*
* Modify:
*
* ****/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 深入学习多线程
{
class Demo2
{
private void ThreadMethod1(object para)
{
Console.WriteLine("开始下载(当前线程编号):"+Thread.CurrentThread.ManagedThreadId); //模拟迅雷下载例子
Thread.Sleep(3000);
Console.WriteLine("下载完毕");
}
//学习“线程池”
public void Test1()
{
//使用线程
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
ThreadPool.QueueUserWorkItem(ThreadMethod1, 123);
Console.ReadLine(); //因为线程池开的线程默认是后台线程,所以必须加这一句
}
public void ThreadMethod2()
{
Console.WriteLine("开始 下载");
Thread.Sleep(2000);
Console.WriteLine("下载完毕");
}
//学习“任务”
public void Test2()
{
Task task = new Task(ThreadMethod2);
task.Start();
Console.ReadLine(); //Task也是后台线程,所以也需要加这一行,不然不执行
}
//介绍“任务工厂”
public void Test3()
{
TaskFactory tf = new TaskFactory();
Task task = tf.StartNew(ThreadMethod2);
Console.ReadLine();
}
static void Main(string[] args)
{
Demo2 demo2 = new Demo2();
demo2.Test3();
}
}
}