一、Task概念
1、什么是进程?
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,【是系统进行资源分配的基本单位】,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,【进程是线程的容器】。程序是指令、数据及其组织形式的描述,进程是程序的实体。
简单概括:进程是程序运行的环境。进程是线程的容器。一个进程可以包含多个线程。
进程系统进行资源分配的基本单位,而线程是系统进行资源分配的最小单位(线程不能再分)。
2、什么是线程?
线程(英语:Thread)是操作系统能够进行【运算调度的最小单位】。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
简单概括:线程是操作系统资源调度的最小单位。线程不能独立运行,必须包含在进程中。进程中可以包含多个线程。多线程执行时是并行,无序的。
串行===>排队===>阻塞(同步) 并行===>无序===>非阻塞(异步)
线程之间要通讯。会有两种方案:同步和异步。
单个线程中能不能异步?可以
多线程肯定是异步。异步不一定是多线程。
多线程中有N个线程,但主线程只有一个,其他的线程都称为分线程。对于单线程程序来说,程序中只有一个线程,这个线程就是主线程。
3、多线程的概念?优点和缺点?
多线程是指程序中包含多个执行流(线程),即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
概括:多线程让程序同时运行多个线程,多个线程并行执行(执行时无顺序)
优点:可以提高CPU的利用率。大大提高了程序的运行效率
缺点:
a.线程也是程序,所以线程运行需要占用计算机资源,线程越多占用资源也越多。(占内存多)
b.多线程需要协调和管理,所以需要CPU跟踪线程,消耗CPU资源。(占cpu多)
c.线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题。(多线程存在资源共享问题 锁)
d.线程太多会导致控制太复杂,最终可能造成很多Bug。(管理麻烦,容易产生bug)
4、什么是线程池?
.NET Framework2.0时代,出现了一个线程池ThreadPool,是一种池化思想,如果需要使用线程,就可以直接到线程池中去获取直接使用,如果使用完毕,在自动的回放到线程池去;
概括:.net 2.0出现线程池,线程池中可以存在多个线程,让线程池来自动管理。
好处:解决了部分Thread管理不便的问题,移除了无用的Thread API。提高线程运行性能。
重要API:QueueUserWorkItem(Callback,data)
5、什么是Task任务?
Task在.net 4.0时出现,是在线程池基础上封装而来的,提供了对线程的延续,取消,等待,超时等方面功能。
Task提供了一种简单和强大的方式来处理异步编程
二、Thread
1、实例化一个分线程
Thread(任务):任务是运行在分线程上的;
Thread thread1 = new Thread(() => {
("线程做的具体的工作,工作一般比较耗时");
("将来也有可能把耗时的任务封装成方法");
});
();
2、obj向线程中传递的数据
Thread thread2 = new Thread((obj) => {
("线程做的具体的工作,工作一般比较耗时2");
("将来也有可能把耗时的任务封装成方法2");
})
();
3、Invoke()
分线程可以【获取】主线程中的资源,分线程中不能修改主线程中的资源,如果要修改分线程中的资源要使用Invoke(),跨线程调用也推荐使用。
Invoke(new Action(() => {
= "abc";
}))
4、线程的属性
= true; // 后台线程
= "线程1"; // 线程名字
= ;
5、winform窗体使用
Winform窗体上的所有的控件一般默认都在主线程中运行,主线程中的死循环:会阻塞,假死,卡顿。
private void button3_Click(object sender, EventArgs e)
{
while (true)
{
("模拟耗时的任务");
}
}
三、Task及工厂模式
1、Task实例化
1)通过构造函数(只实例化,不启动,没有返回值)、没有传递取消标识
Task t1 = new Task(() => {
(1000);
("任务1");
});
();
2)可以取消的任务
CancellationTokenSource cts = new CancellationTokenSource();
Task t2 = new Task(() => {
(1000);
("任务2");
},); // Token标识符
();
3)带参数的任务
Task t3 = new Task((obj) => {
(1000);
("任务3"+obj);
}, "hello");
();
4)实例化并启动,()有返回值,不能向任务传参。
(() =>
{
(1000);
("任务1");
});
5)有返回值的任务
Task<int> t1 = (() =>
{
return 123;
});
// 拿任务返回值 Result
();
6)没有返回值,没有参数,但可以取消任务
CancellationTokenSource cts = new CancellationTokenSource();
(new Action(() =>
{
(1000);
("任务2");
}), );
(); // 取消任务
7)任务嵌套
(() =>
{
//return new List<int> { 1, 2, 3 };
// 任务中又返回任务
return new Task<string>(() => { return "hello"; });
});
2、Task工厂模式
带参数,带返回,带取消标识
CancellationTokenSource cts = new CancellationTokenSource();
Task<string> t3 = ((obj) =>
{
("-------------");
return ();
}, "abc", );
();
WhenAny 任务中的任何一个完成后继续执行的代码配合ContinueWith使用
List<Task> list = new List<Task>()
{
(()=>{
(3000);
("one");
}),
(() =>
{
(6000);
("two");
}),
(() =>
{
(10000);
("three");
})
};
(()).ContinueWith((r) =>
{
("kkluv");
});
WhenAll 任务中的全部任务完成后继续执行的代码配合ContinueWith使用
List<Task> list = new List<Task>()
{
(()=>{
(3000);
("one");
}),
(() =>
{
(6000);
("two");
}),
(() =>
{
(10000);
("three");
})
};
(()).ContinueWith((r) =>
{
("kkluv");
});
WaitAny 任务中的任意一个任务完成后继续执行的代码
List<Task> list = new List<Task>()
{
(()=>{
(3000);
("one");
}),
(() =>
{
(6000);
("two");
}),
(() =>
{
(10000);
("three");
})
};
(());
("def");
WaitAll 任务中的全部任务完成后继续执行的代码
List<Task> list = new List<Task>()
{
(()=>{
(3000);
("one");
}),
(() =>
{
(6000);
("two");
}),
(() =>
{
(10000);
("three");
})
};
(());
("def");