当前位置:   article > 正文

C# 看懂这100+行代码,你就真正入门了(经典)

c#入门必看实力程序100个

老铁

先不废话,简单粗暴,直接来源码:

  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. namespace TestConsole
  8. {
  9. class Program
  10. {
  11. private static ManualResetEvent manualResetEvent = new ManualResetEvent(false);//AutoResetEvent略去
  12. //private static List<int> list = new List<int>();//非线程安全,“集合已修改;可能无法执行枚举操作。”
  13. private static ConcurrentBag<int> list = new ConcurrentBag<int>();
  14. private static CancellationTokenSource cancellationToken = new CancellationTokenSource();
  15. private static ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>();
  16. private static ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>();
  17. static void Main(string[] args)
  18. {
  19. try
  20. {
  21. //ThreadSafetyTest();
  22. //ManualResetEventHandler();
  23. //DelegateTest();
  24. TasKTest();
  25. Console.ReadKey();
  26. }
  27. catch (Exception ex)
  28. {
  29. MessageBox.Show(ex.StackTrace + " " + ex.Message);
  30. }
  31. }
  32. #region TASK用法举例
  33. static void TasKTest()
  34. {
  35. //带返回值的task
  36. Task<String> mytask = Task.Run(async () =>
  37. {
  38. await Task.Delay(5000);
  39. return "老铁666";
  40. }, cancellationToken.Token);
  41. //cancellationToken.Cancel();
  42. while (!mytask.Wait(100)) //在指定时间执行完成就返回true
  43. {
  44. Console.Write(".");
  45. }
  46. Console.WriteLine(mytask.Result);//task任务取消,所以获取task.Result会报错
  47. Task taskFactory = Task.Factory.StartNew(() =>
  48. {
  49. Thread.Sleep(1000);
  50. Console.WriteLine("perfect!");
  51. });
  52. Console.WriteLine(taskFactory.Status);
  53. taskFactory.Wait();//taskFactory任务完成才往下执行
  54. Task.WaitAll(mytask, taskFactory);//所有任务完成再往下执行
  55. Task.WaitAny(mytask, taskFactory);//任一任务完成就往下执行
  56. Console.WriteLine(taskFactory.Status);
  57. Task taskTest = taskFactory.ContinueWith(DoOnSecond);//ContinueWith用法举例
  58. }
  59. static void DoOnSecond(Task t)
  60. {
  61. Console.WriteLine("task {0} finished", t.Id);
  62. Console.WriteLine("this task id {0}", Task.CurrentId);
  63. Console.WriteLine("do some cleanup");
  64. }
  65. #endregion
  66. #region ManualResetEvent 用法举例
  67. private static void ManualResetEventHandler()
  68. {
  69. Thread t1 = new Thread(Thread1);
  70. t1.Start();
  71. Thread t2 = new Thread(Thread2);
  72. t2.Start();
  73. Thread.Sleep(2000);
  74. manualResetEvent.Set();
  75. Thread.Sleep(5000);
  76. t1.Abort();//放弃执行线程t1
  77. Console.WriteLine(t1.ThreadState);
  78. Console.WriteLine(t2.ThreadState);
  79. }
  80. static void Thread1()
  81. {
  82. Console.WriteLine(manualResetEvent.WaitOne().ToString());//等待 manualResetEvent.Set()后执行
  83. manualResetEvent.Reset();// 将信号置为初始状态,即false
  84. //Console.WriteLine(manualResetEvent.WaitOne().ToString());//阻塞当前线程,让他等待着
  85. MessageBox.Show("Thread1 run end");
  86. Parallel.For(0, 100000000, item =>
  87. {
  88. Console.WriteLine(item.ToString());
  89. });
  90. }
  91. static void Thread2()
  92. {
  93. Console.WriteLine(manualResetEvent.WaitOne(10000).ToString());//10秒内收到 manualResetEvent.Set(),即true就往下执行,或者超过100秒,也往下执行,但是状态依然为false
  94. MessageBox.Show("Thread2 run end");
  95. }
  96. #endregion
  97. #region 线程安全之ConcurrentBag 验证
  98. private static void ThreadSafetyTest()
  99. {
  100. int count = 0;
  101. Task t = new Task(() =>
  102. {
  103. while (true)
  104. {
  105. Thread.Sleep(1000);
  106. count++;
  107. list.Add(count);
  108. }
  109. });
  110. t.Start();
  111. Task.Run(() =>
  112. {
  113. while (true)
  114. {
  115. foreach (var item in list)
  116. {
  117. Thread.Sleep(1000);
  118. Console.WriteLine($"{list.Count}");
  119. }
  120. }
  121. });
  122. }
  123. #endregion
  124. public static void DelegateTest()
  125. {
  126. Func<string, string> RetBook = new Func<string, string>(FuncBook);
  127. Console.WriteLine(RetBook("《平凡的世界》"));
  128. }
  129. public static string FuncBook(string BookName)
  130. {
  131. return BookName;
  132. }
  133. }
  134. }

上面代码逻辑要是全懂了,下面就可以跳过了,

没看懂的继续。。。。。。。

① 首先,执行第一个方法ThreadSafetyTest();

涉及知识点:

  1. task的创建和使用;

  2. foreach遍历 

  3. 线程安全集合ConcurrentBag用法

修改这里后运行:

  1. ThreadSafetyTest();
  2. //ManualResetEventHandler();
  3. //DelegateTest();
  4. //TasKTest();

执行结果如下:

a809cd384fd35f8e4bfddb2a41022704.gif

这个方法体的作用主要是开了两个线程,第一个线程每隔1秒向集合添加一个数,第二个线程每隔一秒,便利输出集合。在这里集合要是改成list的,即:

  1. private static ConcurrentBag<int> list = new ConcurrentBag<int>();
  2. 改成=>
  3. private static List<int> list = new List<int>();

运行过程会报错:

非线程安全,“集合已修改;可能无法执行枚举操作。”

原因解释:不管是读还是写,同一时刻只能做一件事情,要么读,要么写,多个线程对同一个集合进行读写操作,就难免会出现线程安全问题,当然你可以

用lock关键字,进行线程同步,但是性能并不是特别理想,然后我尝试使用SynchronizedList<T>来代替使用List<T>达到线程安全的目的。但是发现性能依旧糟糕,于是查看了SynchronizedList<T>的源代码,发现它就是简单的在List<T>提供的API的基础上加了lock,所以性能基本与list<T>方式相差无几。最后使用ConcurrentBag<T>类来实现,性能有很大的改观。

知识拓展:线程安全的队列和字典:

  1. ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>();
  2.  ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>();

② 接下来,执行第二个方法ManualResetEventHandler();

涉及知识点:

  1. ManualResetEvent用法(和AutoResetEvent类似,区别自己去学习);

    主要包括:

    manualResetEvent.Reset();    manualResetEvent.Set();

    manualResetEvent.WaitOne()和manualResetEvent.WaitOne(time)

  2. Thread线程创建和使用;

    重点解释:

    Console.WriteLine(manualResetEvent.WaitOne(10000).ToString());10秒内收到 manualResetEvent.Set(),即true就往下执行,或者超过100秒,也往下执行,但是状态依然为false

    最后的执行结果:

    e728c0f8224d6e7f4cf50afec5bd811e.png

③ 接下来,执行第三个方法DelegateTest();

知识点:带参数,带返回值的委托Func的用法

运行结果:

9accb4882bbe2908e8e2d2b9a29772a9.png

总结一下 :无返回就用action,有返回就用Func

④ 最后,执行第四个方法DelegateTest();

涉及知识点:

  1. task的创建和使用前面已经提供了两种创建方式,这里又提供了新的方式Task.Factory.StartNew(() =>{});

  2. 取消task任务之CancellationTokenSource的用法;

  3. task的线程管控方法Task..Wait(time),Task.WaitAll(), Task.WaitAny(),task.ContinueWith.

运行结果:

cb3c4b6d21385b58bdd6f94ef757e0ff.gif


原创不易,用100+行代码串接这么多重要知识点更加不易。

老铁666

老铁到底溜不溜,在看转发走起来!

进技术交流群的,加小编微信zls20210502,切记备注:进群!

项目工程下载地址:
链接: https://pan.baidu.com/s/1MEm-CjQjrReP6jxyqpLjQA 

提取码: wr3n 

欢迎关注公众号: dotnet编程大全

技术群: 需要进技术群的添加小编微信mm1552923,备注:加群;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/454688
推荐阅读
相关标签
  

闽ICP备14008679号