第5章:使用C#5.0

1、异步函数async

    1)、异步函数需要使用async关键词标注方法,异步函数必须返回Task或Task<int>,可以使用async void方法(唯一合理在程序UI控制器事件处理器中),其余更推荐async Task。

    2)、async方法内部,可以使用await操作符,在async外不能使用await,另外异步函数至少要一个await关键字。

    3)、await调用后方法立即返回,即GetStringAsync()不会Thread.Sleep(2),而是在取Result的时候等待。

        async static Task<string> GetStringAsync()
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            return "Hello World!";
        }
View Code
        static void Main(string[] args)
        {
            Console.WriteLine(DateTime.Now);
            var str = GetStringAsync();
            Console.WriteLine(DateTime.Now);
            //Thread.Sleep(TimeSpan.FromSeconds(5));
            Console.WriteLine(str.Result);
            Console.WriteLine(DateTime.Now);
            Console.Read();
        }
View Code

  --如果是两个await,两个await不是两个异步任务,而是先完成前面的await才去做下一个await,从而避免Task这种不知道执行顺序的尴尬。

        async static Task<string> GetStringAsync()
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            await Task.Delay(TimeSpan.FromSeconds(2));
            return "Hello World!";
        }

        static void Main(string[] args)
        {
            Console.WriteLine(DateTime.Now);
            var str = GetStringAsync();
            Console.WriteLine(DateTime.Now);
            //Thread.Sleep(TimeSpan.FromSeconds(5));
            Console.WriteLine(str.Result);
            // 等待4秒而不是2秒
            Console.WriteLine(DateTime.Now);
            Console.Read();
        }
View Code

  --不能再catch、finally、lock或unsafe中使用await,不允许异步函数使用ref和out

2、使用await操作符获取异步任务结果

 -- 有异常的时候,TaskContinuationOptions.OnlyOnFaulted;没有异常的时候,TaskContinuationOptions.NotOnFaulted。

--Task.wait(),Task.Result()不推荐在GUI和asp.net中使用

-- TPL模式

        static Task AsynchronyWithTPL()
        {
            Task<string> t = GetInfoAsync("Task 1");
            Task t2 = t.ContinueWith(task => Console.WriteLine(t.Result), TaskContinuationOptions.NotOnFaulted);
            Task t3 = t.ContinueWith(task => Console.WriteLine(t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted);
            return Task.WhenAny(t2, t3);
        }

        async static Task<string> GetInfoAsync(string name)
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            //throw new Exception("Boom!");
            return string.Format($"{name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}");
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyWithTPL();
            t.Wait();
            Console.Read();
        }
View Code

--用async、await方法

        async static Task AsynchronyWithAwait()
        {
            try
            {
                string result = await GetInfoAsync("Task 2");
                Console.WriteLine(result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }

        async static Task<string> GetInfoAsync(string name)
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            //throw new Exception("Boom!");
            return string.Format($"{name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}");
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyWithAwait();
            t.Wait();
            Console.Read();
        }
View Code

3、在lambda表达式中使用await操作符

        async static Task AsynchronyProcessing()
        {
            Func<string, Task<string>> asyncLambda = async name =>
            {
                await Task.Delay(TimeSpan.FromSeconds(2));
                return $"Task {name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                    $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}";
            };
            string result = await asyncLambda("async lambda");
            Console.WriteLine(DateTime.Now);
            Console.WriteLine(result);
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyProcessing();
            Console.WriteLine(DateTime.Now);
            t.Wait();
            Console.Read();
        }
View Code

4、对连续的异步任务使用await操作符

 -- 通过Task.ContinueWith来分步执行

       static Task AsynchronyWithTPL()
        {
            var containerTask = new Task(() =>
            {
                Task<string> t = GetInfoAsync("TPL 1");
                t.ContinueWith(task =>
                {
                    Console.WriteLine(t.Result);
                    Task<string> t2 = GetInfoAsync("TPL 2");

                    t2.ContinueWith(innerTask => Console.WriteLine(innerTask.Result), 
                        TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);

                    t2.ContinueWith(innerTask => Console.WriteLine(innerTask.Exception.InnerException),
                        TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
                }, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);

                t.ContinueWith(task => Console.WriteLine(t.Exception.InnerException),
                   TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
            });
            containerTask.Start();
            return containerTask;
        }

        async static Task<string> GetInfoAsync(string name)
        {
            Console.WriteLine($"Task {name} started");
            await Task.Delay(TimeSpan.FromSeconds(2));
            if (name == "TPL 2")
            {
                throw new Exception("Boom!");
            }
            return $"Task {name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}";
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyWithTPL();
            t.Wait();
            Console.Read();
        }
View Code

-- await更简单,异步函数并不一定是并行执行的,可能是顺序执行

        async static Task AsynchronyWithAwait()
        {
            try
            {
                string result = await GetInfoAsync("Async 1");
                Console.WriteLine(result);
                result = await GetInfoAsync("Async 2");
                Console.WriteLine(result);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        async static Task<string> GetInfoAsync(string name)
        {
            Console.WriteLine($"Task {name} started");
            await Task.Delay(TimeSpan.FromSeconds(2));
            if (name == "TPL 2" || name == "Async 2")
            {
                throw new Exception("Boom!");
            }
            return $"Task {name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}";
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyWithAwait();
            t.Wait();
            Console.Read();
        }
View Code

5、对并行执行的异步任务使用await操作符

--Task 1和Task 2在线程池不同线程中执行,是并行任务。

        async static Task AsynchronyProcessing()
        {
            Task<string> t1 = GetInfoAsync("Task 1", 3);
            Task<string> t2 = GetInfoAsync("Task 2", 5);

            string[] results = await Task.WhenAll(t1, t2);
            foreach (string result in results)
            {
                Console.WriteLine(result);
            }
        }

        async static Task<string> GetInfoAsync(string name, int seconds)
        {
            Console.WriteLine($"1、{name}---{DateTime.Now}");
            await Task.Delay(TimeSpan.FromSeconds(seconds));
            Console.WriteLine($"2、{name}---{DateTime.Now}");
            await Task.Run(() => {
                Thread.Sleep(TimeSpan.FromSeconds(seconds));
            });
            Console.WriteLine($"3、{name}---{DateTime.Now}");
            return $"{name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}." +
                $"Is thread pool thread:{Thread.CurrentThread.IsThreadPoolThread}";
        }

        static void Main(string[] args)
        {
            Task t = AsynchronyProcessing();
            t.Wait();
            Console.Read();
        }
View Code

 

posted @ 2022-01-27 16:36  江境纣州  阅读(159)  评论(0编辑  收藏  举报