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.

运行结果:


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

老铁666

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

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

提取码: wr3n 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值