多线程 Task学习
线程启动的四种方式:
方式1:
Task task = new Task(() => { Console.WriteLine($"启动线程方式一,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }); task.Start();
方式2:
Task.Run(() => { Console.WriteLine($"启动线程方式二,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); });
方式3:
TaskFactory taskFactory = new TaskFactory(); taskFactory.StartNew(() => { Console.WriteLine($"启动线程方式三,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); });
方式4:
TaskFactory taskFactoryTwo = Task.Factory; taskFactoryTwo.StartNew(() => { Console.WriteLine($"启动线程方式四,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); });
整体代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
static void Main(string[] args) { Console.WriteLine($"*** Start,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")},时间:{DateTime.Now}***"); Task task = new Task(() => { Console.WriteLine($"启动线程方式一,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }); task.Start(); Task.Run(() => { Console.WriteLine($"启动线程方式二,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }); TaskFactory taskFactory = new TaskFactory(); taskFactory.StartNew(() => { Console.WriteLine($"启动线程方式三,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }); TaskFactory taskFactoryTwo = Task.Factory; taskFactoryTwo.StartNew(() => { Console.WriteLine($"启动线程方式四,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }); Console.WriteLine($"*** End,当前线程id:{Thread.CurrentThread.ManagedThreadId.ToString("00")},时间:{DateTime.Now}***"); Console.ReadKey(); }
运行结果:
Thread.Sleep()和Task.Delay()的区别:
Thread.Sleep()会等待线程(线程阻塞),Task.Delay()不会等待线程(非阻塞)
代码实现对比:
Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Thread.Sleep(3000);//等待3000ms,会等待线程 stopwatch.Stop(); Console.WriteLine($"Thread.Sleep(3000)执行 总耗时长:{stopwatch.ElapsedMilliseconds} ms"); Stopwatch stopwatch1 = new Stopwatch(); stopwatch1.Start(); Task.Delay(3000);//等待3000ms,不会等待线程,而是在等待多久以后,去执行些事件等 stopwatch1.Stop(); Console.WriteLine($"Task.Delay(3000)执行 总耗时长:{stopwatch1.ElapsedMilliseconds} ms");
结果:
Task.Delay用途:一般是在等待多久之后,去执行些事件
示例代码:
Stopwatch stopwatch2 = new Stopwatch(); Console.WriteLine("开始计时"); stopwatch2.Start(); Task.Delay(3000).ContinueWith(s => {//不阻塞主线程, Console.WriteLine("去执行事件"); stopwatch2.Stop(); Console.WriteLine("结束计时"); Console.WriteLine($"Task.Delay(3000)执行 总耗时长:{stopwatch2.ElapsedMilliseconds} ms"); });
结果:
线程任务控制:
开启3个线程任务,当任务全部完成后,执行最后的提示:
代码
List<Task> taskList = new List<Task>(); TaskFactory taskFactory = Task.Factory; Console.WriteLine($"开始执行所有线程,当前时间为:{DateTime.Now}"); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 5000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); })); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 5000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); })); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 5000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); })); Task.WaitAll(taskList.ToArray()); Console.WriteLine($"所有线程都执行完成,当前时间为:{DateTime.Now}");
执行结果:
开启三个线程,当第一个线程执行完成,就进行提示(不影响后面线程执行):
代码:
List<Task> taskList = new List<Task>(); TaskFactory taskFactory = Task.Factory; Console.WriteLine($"开始执行所有线程,当前时间为:{DateTime.Now}"); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); })); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); })); taskList.Add(taskFactory.StartNew(() => { Thread.Sleep(new Random().Next(3000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); })); //Task.WaitAll(taskList.ToArray()); //Console.WriteLine($"所有线程都执行完成,当前时间为:{DateTime.Now}"); taskFactory.ContinueWhenAny(taskList.ToArray(), ts => { Console.WriteLine($"第一个线程执行完成,当前时间为:{DateTime.Now}"); });
结果:
开启三个线程,当第一个线程执行完成,就进行提示,并将线程参数传入到提示内容中(不影响后面线程执行):
代码:
List<Task> taskList = new List<Task>(); TaskFactory taskFactory = Task.Factory; Console.WriteLine($"开始执行所有线程,当前时间为:{DateTime.Now}"); taskList.Add(taskFactory.StartNew(obj => { Thread.Sleep(new Random().Next(1000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); },$"传入参数为03")); taskList.Add(taskFactory.StartNew(obj => { Thread.Sleep(new Random().Next(2000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); }, $"传入参数为03")); taskList.Add(taskFactory.StartNew(obj => { Thread.Sleep(new Random().Next(3000, 8000)); Console.WriteLine($"当前线程:{Thread.CurrentThread.ManagedThreadId.ToString("00")},当前时间为:{DateTime.Now}"); }, $"传入参数为03")); //Task.WaitAll(taskList.ToArray()); //Console.WriteLine($"所有线程都执行完成,当前时间为:{DateTime.Now}"); taskFactory.ContinueWhenAny(taskList.ToArray(), ts => { Console.WriteLine($"当前传入参数:{ts.AsyncState},第一个线程执行完成,当前时间为:{DateTime.Now}"); });
结果: