1.线程池的作用
每当启动一个线程都是有消耗的,线程池通过预先创建可回收线程的池来降低这个开销,且能够对线程进行有效调度,使处理器不至于超负荷。
2.如何将代码运行在线程池中:
Task.Run(委托);
示例:
static void Main(string[] args)
{
Console.WriteLine("主线程【{0}】,开始执行",GetCurrentThreadId());
Task.Run(LogRunningState);
Task.Run(LogRunningState);
Console.WriteLine("主线程【{0}】,执行完毕",GetCurrentThreadId());
Console.ReadLine();
}
/// <summary>
/// 打印运行状态
/// </summary>
private static void LogRunningState()
{
var threadTag = Thread.CurrentThread.IsBackground ? "后台线程" : "前台线程";
var threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("【{0}】线程【{1}】开始执行",threadTag,threadId);
Console.WriteLine("【{0}】线程【{1}】执行完毕",threadTag,threadId);
}
/// <summary>
/// 获取当前线程id
/// </summary>
private static int GetCurrentThreadId()
{
return Thread.CurrentThread.ManagedThreadId;
}
输出:
可见,默认状态下,线程池中的线程为后台线程。
3.Task的是什么?
Task代表了一个并发操作,默认使用线程池中的线程来执行操作,在执行Task.Run时将返回一个Task对象。
4.如何获得Task结果?
1.无返回Task直接调用其Wait方法,该Wait方法将阻塞当前线程直至Task完成,示例如下:
static void Main(string[] args)
{
Console.WriteLine("主线程【{0}】,开始执行",GetCurrentThreadId());
var task1 = Task.Run(LogRunningState);
task1.Wait();
var task2 = Task.Run(LogRunningState);
task2.Wait();
Console.WriteLine("主线程【{0}】,执行完毕",GetCurrentThreadId());
}
/// <summary>
/// 打印运行状态
/// </summary>
private static void LogRunningState()
{
var threadTag = Thread.CurrentThread.IsBackground ? "后台线程" : "前台线程";
var threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("【{0}】线程【{1}】开始执行",threadTag,threadId);
Console.WriteLine("【{0}】线程【{1}】执行完毕",threadTag,threadId);
}
/// <summary>
/// 获取当前线程id
/// </summary>
private static int GetCurrentThreadId()
{
return Thread.CurrentThread.ManagedThreadId;
}
输出:
2.有返回值Task,可直接调用Result,若Task还未执行完毕,则会阻塞当前线程,直至Task执行完毕。示例如下:
static void Main(string[] args)
{
Console.WriteLine("主线程【{0}】,开始执行",GetCurrentThreadId());
var task1 = Task.Run(() => GetSumOfNumbers(new List<int>() { 1, 2, 3 }));
task1.Wait();
var sum=task1.Result;
Console.WriteLine("和为:{0}",sum);
Console.WriteLine("主线程【{0}】,执行完毕",GetCurrentThreadId());
}
/// <summary>
/// 获得数值和
/// </summary>
private static int GetSumOfNumbers(List<int> numbers)
{
var sum = 0;
foreach (var number in numbers)
{
sum += number;
}
return sum;
}
输出:
5.如何在Task执行完毕后,执行指定内容?
1.调用Task的Continue方法
static void Main(string[] args)
{
Console.WriteLine("主线程【{0}】,开始执行",GetCurrentThreadId());
var task= Task.Run(()=>GetSumOfNumbers(new List<int>(){1,2,3}));
task.ContinueWith(LogTaskResult);
Console.WriteLine("主线程【{0}】,执行完毕",GetCurrentThreadId());
Console.ReadLine();
}
/// <summary>
/// 获得数值和
/// </summary>
private static int GetSumOfNumbers(List<int> numbers)
{
var sum = 0;
foreach (var number in numbers)
{
sum += number;
}
return sum;
}
/// <summary>
/// 打印任务结果
/// </summary>
/// <param name="task">任务</param>
private static void LogTaskResult(Task<int> task)
{
Console.WriteLine(task.Result);
}
输出:
2.Task执行GetAwaiter()获得一个Awaiter对象,可通过此对象的GetResult获取Task执行结果和OnCompleted方法传入结束后要执行的逻辑。
static void Main(string[] args)
{
Console.WriteLine("主线程【{0}】,开始执行",GetCurrentThreadId());
var task= Task.Run(()=>GetSumOfNumbers(new List<int>(){1,2,3}));
var taskAwaiter = task.GetAwaiter();
taskAwaiter.OnCompleted(()=>LogNumber(taskAwaiter.GetResult()));
Console.WriteLine("主线程【{0}】,执行完毕",GetCurrentThreadId());
Console.ReadLine();
}
/// <summary>
/// 获得数值和
/// </summary>
private static int GetSumOfNumbers(List<int> numbers)
{
var sum = 0;
foreach (var number in numbers)
{
sum += number;
}
return sum;
}
/// <summary>
/// 打印数字
/// </summary>
/// <param name="number">数字</param>
private static void LogNumber(int number)
{
Console.WriteLine(number);
}
输出: