打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

老铁

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

using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;
namespace TestConsole{ class Program { private static ManualResetEvent manualResetEvent = new ManualResetEvent(false);//AutoResetEvent略去 //private static List<int> list = new List<int>();//非线程安全,“集合已修改;可能无法执行枚举操作。” private static ConcurrentBag<int> list = new ConcurrentBag<int>(); private static CancellationTokenSource cancellationToken = new CancellationTokenSource(); private static ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>(); private static ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>(); static void Main(string[] args) { try { //ThreadSafetyTest(); //ManualResetEventHandler(); //DelegateTest(); TasKTest();
Console.ReadKey(); } catch (Exception ex) { MessageBox.Show(ex.StackTrace + " " + ex.Message); } } #region TASK用法举例 static void TasKTest() { //带返回值的task Task<String> mytask = Task.Run(async () => { await Task.Delay(5000); return "老铁666"; }, cancellationToken.Token); //cancellationToken.Cancel(); while (!mytask.Wait(100)) //在指定时间执行完成就返回true { Console.Write("."); } Console.WriteLine(mytask.Result);//task任务取消,所以获取task.Result会报错
Task taskFactory = Task.Factory.StartNew(() => { Thread.Sleep(1000); Console.WriteLine("perfect!"); }); Console.WriteLine(taskFactory.Status); taskFactory.Wait();//taskFactory任务完成才往下执行 Task.WaitAll(mytask, taskFactory);//所有任务完成再往下执行 Task.WaitAny(mytask, taskFactory);//任一任务完成就往下执行 Console.WriteLine(taskFactory.Status);
Task taskTest = taskFactory.ContinueWith(DoOnSecond);//ContinueWith用法举例 } static void DoOnSecond(Task t) { Console.WriteLine("task {0} finished", t.Id); Console.WriteLine("this task id {0}", Task.CurrentId); Console.WriteLine("do some cleanup"); } #endregion
#region ManualResetEvent 用法举例 private static void ManualResetEventHandler() { Thread t1 = new Thread(Thread1); t1.Start(); Thread t2 = new Thread(Thread2); t2.Start(); Thread.Sleep(2000); manualResetEvent.Set(); Thread.Sleep(5000); t1.Abort();//放弃执行线程t1 Console.WriteLine(t1.ThreadState); Console.WriteLine(t2.ThreadState); } static void Thread1() { Console.WriteLine(manualResetEvent.WaitOne().ToString());//等待 manualResetEvent.Set()后执行 manualResetEvent.Reset();// 将信号置为初始状态,即false //Console.WriteLine(manualResetEvent.WaitOne().ToString());//阻塞当前线程,让他等待着 MessageBox.Show("Thread1 run end"); Parallel.For(0, 100000000, item => { Console.WriteLine(item.ToString()); }); }
static void Thread2() { Console.WriteLine(manualResetEvent.WaitOne(10000).ToString());//10秒内收到 manualResetEvent.Set(),即true就往下执行,或者超过100秒,也往下执行,但是状态依然为false MessageBox.Show("Thread2 run end"); } #endregion
#region 线程安全之ConcurrentBag 验证 private static void ThreadSafetyTest() { int count = 0; Task t = new Task(() => { while (true) { Thread.Sleep(1000); count++; list.Add(count); } }); t.Start();
Task.Run(() => { while (true) { foreach (var item in list) { Thread.Sleep(1000); Console.WriteLine($"{list.Count}"); } } });
} #endregion
public static void DelegateTest() { Func<string, string> RetBook = new Func<string, string>(FuncBook); Console.WriteLine(RetBook("《平凡的世界》"));
} public static string FuncBook(string BookName) { return BookName; }

}}

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

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

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

涉及知识点:

  1. task的创建和使用;

  2. foreach遍历 

  3. 线程安全集合ConcurrentBag用法

修改这里后运行:

ThreadSafetyTest(); //ManualResetEventHandler(); //DelegateTest(); //TasKTest();              

执行结果如下:

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

private static ConcurrentBag<int> list = new ConcurrentBag<int>(); 改成=>private static List<int> list = new List<int>();

运行过程会报错:

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

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

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

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

ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>(); 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

    最后的执行结果:

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

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

运行结果:

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

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

涉及知识点:

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

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

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

运行结果:

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
(转)改善C#程序的建议9:使用Task代替ThreadPool和Thread
C# 多线程入门系列(二)
C# Task的使用
[深入学习C#]C#实现多线程的方式:Task
并行编程和任务(二)
浅谈线程池(下):相关试验及注意事项 - 老赵点滴 - 追求编程之美 - 博客园
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服