码迷,mamicode.com
首页 > Web开发 > 详细

.net的 async 和 await

时间:2016-07-01 16:01:06      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:

async 和 await 出现在C# 5.0之后,关系是两兄弟,Task是父辈,Thread是爷爷辈,这就是.net 多线程处理的东西,具体包括 创建线程,线程结果返回,线程中止,线程中的异常处理

1 线程创建的几个方式

技术分享
 static void Main(string[] args)
        {
            new Thread(NewThread).Start();//这里需要注意:创建一个 new Thread()的实例的时候,需要手动调用它的Start()去启动这个实例,
            //对于Task来说StartNew和Run的同时,既会创建新的线程,又会自动启动这个线程
            Task.Factory.StartNew(NewThread);
            Task.Run(new Action(NewThread));
        }
        public static void NewThread()
        {
            Console.WriteLine("我是一个New线程!");
        }
View Code

2 使用线程池

技术分享
        //线程的创建是比较耗费资源的一件事情,.net提供了线程池来帮助创建和管理线程,Task默认会直接使用线程池
        //但是Thread不会,如果不使用Task,又想使用线程池,可以使用ThreadPool类

        static void Main(string[] args)
        {
            Console.WriteLine("我是主线程:ThreadId为{0}", Thread.CurrentThread.ManagedThreadId);
            ThreadPool.QueueUserWorkItem(NewThread);
            Console.ReadKey();
        }
        public static void NewThread(object data)
        {
            Console.WriteLine("我是一个New线程,线程Id是{0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadKey();
        }
View Code

3 传入参数

技术分享
 //传入参数
        static void Main(string[] args)
        {
            new Thread(NewThread).Start("arg1");//没有匿名委托之前只能这样传入一个参数
            //有了匿名委托之后,可以传入多个参数
            new Thread(delegate()
                {
                    NewThread2("arg1", "arg2", "arg3");
                }).Start();

            //Lambda匿名委托
            new Thread(() =>
            {
                NewThread2("arg1", "arg2", "arg3");
            }).Start();
        }
        public static void NewThread()
        {
            Console.WriteLine("我是一个New线程!");
        }
        public static void NewThread2(string arg1, string arg2, string arg3)
        {
            Console.WriteLine("我是一个New线程!");
        }
View Code

4 返回值

技术分享
        //返回值
        //Thread这玩意是没有返回值的,但是高级的Task可以
        static void Main(string[] args)
        {
            var str = Task.Run<string>(() =>
             {
                 return DateTime.Now.ToString();
             });
        }
View Code

5 线程之间数据共享

技术分享
        //线程之间共享数据问题(这种存在问题:如果第一个线程还没来得及把_isOK设置为True,第二个线程就进来了,这样在多线程情况下,结果不可预知,这就是线程不安全)
        private static bool _isOK = false;
        static void Main(string[] args)
        {
            new Thread(DoOk).Start();
            Task.Factory.StartNew(DoOk);
            Task.Run(() =>
            {
                DoOk();
            });

            Task.Run(new Action(DoOk));
        }

        static void DoOk()
        {
            if (!_isOK)
            {
                Console.WriteLine("OK");
                _isOK = true;
                Console.ReadKey();
            }
        }
View Code

6 独占锁

技术分享
 //解决上面线程不安全的问题就要用到锁(锁的类型有 读写锁,独占锁,互斥锁)
        //独占锁
        private static bool _isOK = false;
        private static object _lock = new object();
        static void Main(string[] args)
        {
            new Thread(DoOk).Start();
            Task.Factory.StartNew(DoOk);
            Task.Run(() =>
            {
                DoOk();
            });

            Task.Run(new Action(DoOk));
        }

        static void DoOk()
        {
            lock (_lock)//独占锁,加上锁之后,被锁的代码在同一个时间内,只允许一个线性进行访问,
            //其他线程会被阻塞排队,只有这个线程被释放之后,其他线程才能执行被锁的代码,因为这时候,之前的线程已经访问完毕,锁已经被释放
            {
                if (!_isOK)
                {
                    Console.WriteLine("OK");
                    _isOK = true;
                    Console.ReadKey();
                }
            }
        }
View Code

7 线程量(信号量)

技术分享
        //SemaphoreSlim 可以控制对某一段代码或者对某个资源访问的线程的数量,超过这个数量其他线程就得等待,等可以访问的数量的线程访问完之后,其他线程才可以继续访问,
        //跟锁的原理相似,但不是独占的,可以允许一定数量的线程同时访问

        static SemaphoreSlim _sem = new SemaphoreSlim(3);
        static void Main(string[] args)
        {
            for (int i = 1; i <= 5; i++)
            {
                //new Thread(() => 
                //{
                //    Entry(i);
                //}).Start();
                new Thread(Entry).Start(i);
            }
        }
        static void Entry(object id)
        {
            Console.WriteLine(id + "开始排队...");
            _sem.Wait();
            Console.WriteLine(id + "开始执行...");
            Thread.Sleep(1000 * (int)id);
            Console.WriteLine(id + "执行完毕,离开");
            _sem.Release();
            Console.ReadKey();
        }
View Code

8 捕获异常

a:

技术分享
 //使用Thread 线程的异常处理(其他线程的异常,主线程能捕获到么?)
        static void Main(string[] args)
        {
            try
            {
                new Thread(Entry).Start();
            }
            catch (Exception ee)
            {
                //这里其他线程的异常是捕获不到的
                Console.WriteLine("捕获到异常!");
            }
            Console.ReadKey();
        }
        static void Entry()
        {
            throw null;
        }
View Code

 b:

技术分享
    static void Main(string[] args)
        {
            try
            {
                var task = Task.Run(() =>
                   {
                       Entry();
                   });
                task.Wait();//调用这句话之后主线程才能捕获task里面的异常

                //对于有返回值的Task,接收了它的返回值就不需要再调用Wait(),Entry2()里面的异常有可以捕获到
                var task2 = Task.Run(() =>
                {
                    return Entry2();
                });
               var name = task2.Result;
            }
            catch (Exception)
            {

                Console.WriteLine("捕获到异常!");
                Console.ReadKey();
            }
        }
        static void Entry()
        {
            throw null;
        }
        static string Entry2()
        {
            throw null;
        }
View Code

 

.net的 async 和 await

标签:

原文地址:http://www.cnblogs.com/niuzaihenmang/p/5633314.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!