小言_互联网的博客

C# Task任务队列

328人阅读  评论(0)

新建一个Winfrom项目,加入下面代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using System.Windows.Forms;
  6. namespace 线程2
  7. {
  8. public partial class Form1 : Form
  9. {
  10. public Form1()
  11. {
  12. InitializeComponent();
  13. }
  14. private void Form1_Load(object sender, EventArgs e)
  15. {
  16. Task task1 = new Task(() =>
  17. {
  18. Thread.Sleep( 400);
  19. Console.WriteLine( "task1");
  20. });
  21. Task task2 = new Task(() =>
  22. {
  23. Thread.Sleep( 300);
  24. Console.WriteLine( "task2");
  25. });
  26. Task task3 = new Task(() =>
  27. {
  28. Thread.Sleep( 200);
  29. Console.WriteLine( "task3");
  30. });
  31. Task task4 = new Task(() =>
  32. {
  33. Thread.Sleep( 100);
  34. Console.WriteLine( "task4");
  35. });
  36. task1.Start();
  37. task2.Start();
  38. task3.Start();
  39. task4.Start();
  40. }
  41. }
  42. }

运行:

由于延时不同,最先执行的Task1,反而最后一个执行完,那么如果要求从任务1,一直执行到任务4,怎么写呢?

代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using System.Windows.Forms;
  6. namespace 线程 2
  7. {
  8. public partial class Form1 : Form
  9. {
  10. public Form1()
  11. {
  12. InitializeComponent();
  13. }
  14. private List<Task> TaskList = new List<Task>();
  15. private void Form1_Load(object sender, EventArgs e)
  16. {
  17. Task task1 = new Task(() =>
  18. {
  19. Thread.Sleep( 400);
  20. Console.WriteLine( "task1");
  21. });
  22. Task task2 = new Task(() =>
  23. {
  24. Thread.Sleep( 300);
  25. Console.WriteLine( "task2");
  26. });
  27. Task task3 = new Task(() =>
  28. {
  29. Thread.Sleep( 200);
  30. Console.WriteLine( "task3");
  31. });
  32. Task task4 = new Task(() =>
  33. {
  34. Thread.Sleep( 100);
  35. Console.WriteLine( "task4");
  36. });
  37. TaskList.Add(task1);
  38. TaskList.Add(task2);
  39. TaskList.Add(task3);
  40. TaskList.Add(task4);
  41. foreach (Task task in TaskList)
  42. {
  43. task.Start();
  44. task.Wait();
  45. }
  46. }
  47. }
  48. }

运行:

用上面的方法虽然有效,但会阻塞主线程,导致winfrom界面卡住,无法操作,下面就用异步的方法解决问题

代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using System.Windows.Forms;
  6. namespace 线程2
  7. {
  8. public partial class Form1 : Form
  9. {
  10. public Form1()
  11. {
  12. InitializeComponent();
  13. }
  14. private List<Task> TaskList = new List<Task>();
  15. private void Form1_Load(object sender, EventArgs e)
  16. {
  17. }
  18. private void Button_Calculate_Click(object sender, EventArgs e)
  19. {
  20. Task task1 = new Task( async () =>
  21. {
  22. await Task.Delay(TimeSpan.FromSeconds( 4));
  23. Console.WriteLine( "task1");
  24. });
  25. Task task2 = new Task( async () =>
  26. {
  27. await Task.Delay(TimeSpan.FromSeconds( 3));
  28. Console.WriteLine( "task2");
  29. });
  30. Task task3 = new Task( async () =>
  31. {
  32. await Task.Delay(TimeSpan.FromSeconds( 2));
  33. Console.WriteLine( "task3");
  34. });
  35. Task task4 = new Task( async () =>
  36. {
  37. await Task.Delay(TimeSpan.FromSeconds( 1));
  38. Console.WriteLine( "task4");
  39. });
  40. TaskList.Add(task1);
  41. TaskList.Add(task2);
  42. TaskList.Add(task3);
  43. TaskList.Add(task4);
  44. foreach (Task task in TaskList)
  45. {
  46. task.Start();
  47. task.Wait();
  48. }
  49. }
  50. }
  51. }

运行:

用异步方式虽然界面不会卡住,但另一个问题来了,task.wait()方法似乎没有效果。里面的任务队列依然没有按顺序来执行。

经过一段时间的研究,后面我终于找到方法了,用下面的方法既不会卡住UI,也会按照队列来执行,虽然写法不是特别好,读者可以按下面方法自己封装了。


  
  1. private void Test()
  2. {
  3. Task.Run(() =>
  4. {
  5. Task t1 = new Task(() => {
  6. Thread.Sleep( 2000);
  7. Console.WriteLine( "t1");
  8. num = 1;
  9. });
  10. t1.Start();
  11. t1.Wait();
  12. Task t2 = new Task(() => {
  13. Thread.Sleep( 1000);
  14. Console.WriteLine( "t2");
  15. num = 3;
  16. });
  17. t2.Start();
  18. t2.Wait();
  19. Console.WriteLine( "线程执行完毕");
  20. });
  21. }

运行:

也可以这样写:


  
  1. private async void Test()
  2. {
  3. await Task.Run( async () =>
  4. {
  5. await Task.Delay( 4000);
  6. Trace.WriteLine( "第1个线程执行");
  7. });
  8. await Task.Run( async () =>
  9. {
  10. await Task.Delay( 3000);
  11. Trace.WriteLine( "第2个线程执行");
  12. });
  13. await Task.Run( async () =>
  14. {
  15. await Task.Delay( 2000);
  16. Trace.WriteLine( "第3个线程执行");
  17. });
  18. }

运行:

对现有代码进行封装:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. namespace Utils
  5. {
  6. public class TaskQueue
  7. {
  8. /// <summary>
  9. /// 任务列表
  10. /// </summary>
  11. private List<Task> TaskList = null;
  12. /// <summary>
  13. /// 是否在执行任务中
  14. /// </summary>
  15. private bool isPerformTask = false;
  16. /// <summary>
  17. /// 执行完任务的回调
  18. /// </summary>
  19. public Action CallBack = null;
  20. private static TaskQueue _instance = null;
  21. public static TaskQueue Instance
  22. {
  23. get
  24. {
  25. if (_instance == null)
  26. _instance = new TaskQueue();
  27. return _instance;
  28. }
  29. }
  30. /// <summary>
  31. /// 添加任务
  32. /// </summary>
  33. /// <param name="task"></param>
  34. public void AddTask(Task task)
  35. {
  36. if (isPerformTask)
  37. {
  38. Console.WriteLine( "[TaskQueue]任务正在执行中,此时不能做赋值操作");
  39. return;
  40. }
  41. if (task != null)
  42. {
  43. TaskList.Add(task);
  44. }
  45. }
  46. /// <summary>
  47. /// 执行任务
  48. /// </summary>
  49. public void PerformTask()
  50. {
  51. if (isPerformTask)
  52. {
  53. Console.WriteLine( "[TaskQueue]任务正在执行中,不可重复调用");
  54. return;
  55. }
  56. if (TaskList == null || TaskList.Count == 0)
  57. {
  58. Console.WriteLine( "[TaskQueue]任务列表为空");
  59. return;
  60. }
  61. Task.Run(() =>
  62. {
  63. isPerformTask = true;
  64. foreach (Task item in TaskList)
  65. {
  66. item.Start();
  67. item.Wait();
  68. }
  69. TaskList.Clear();
  70. isPerformTask = false;
  71. if (CallBack != null) CallBack();
  72. });
  73. }
  74. private TaskQueue()
  75. {
  76. TaskList = new List<Task>();
  77. }
  78. }
  79. }

调用:


  
  1. Task task1 = new Task(() =>
  2. {
  3. Thread.Sleep( 1000);
  4. Console.WriteLine( "t1");
  5. });
  6. Task task2 = new Task(() =>
  7. {
  8. Thread.Sleep( 2000);
  9. Console.WriteLine( "t2");
  10. });
  11. Task task3 = new Task(() =>
  12. {
  13. Console.WriteLine( "t3");
  14. });
  15. Action callback = () =>
  16. {
  17. Console.WriteLine( "所有任务执行完成");
  18. };
  19. TaskQueue.Instance.AddTask(task1);
  20. TaskQueue.Instance.AddTask(task2);
  21. TaskQueue.Instance.AddTask(task3);
  22. TaskQueue.Instance.CallBack = callback;
  23. TaskQueue.Instance.PerformTask();

运行:

 

如果你这个帖子对你有用,欢迎给我点赞 + 留言,谢谢

end


转载:https://blog.csdn.net/qq_38693757/article/details/117361771
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场