zoukankan      html  css  js  c++  java
  • Framework4.5语法糖 异步Task

    1、线程安全

    在使用TaskRun的时候需要注意线程安全的问题。

    线程安全通常是由全局变量及静态变量引起的,如果是值类型就不存在这样的隐患,如果是引用类型用不好就会导致线程不安全!

    2、Task、Task<T>存在的意义

    这问题困扰了我很久,包括到现在还是有问题没想明白。

    Task可以等同于void的线程,那么Task能节约时间是能理解的。

    Task<T>能省时间吗?答案是能,Debug的时候我曾陷入一个误区,误认为Task<T>的方法是串行的,其实是并行的,比如有3个异步方法,方法1耗时3秒,方法2耗时6秒,方法3耗时4秒,串行肯定是13秒,但在Task<T>下3个方法是并行的,总耗时约等于最长耗时的方法2也就是6秒。脑部一下3个方法在同时执行,方法1先结束并返回值、方法3接着结束并返回值,方法2最后结束并返回返回值。如果在总方法里面还有一个var m=a+b+c,则m可理解为3个方法都结束后再来调用。

    OK,上面举得例子是3个无关的方法,加入方法2的参数是方法1的返回值,又是什么情况呢?实践证明,framework已经把它处理成了方法2必须等待方法1全部执行完才执行,也就是总耗时为3+6=9秒,方法三的时间在并行时自动节约掉了!!

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                DateTime dtBegin = DateTime.Now;
                var delayTask = DisplayValue();
                
                DisplayValue3();
                int x = delayTask.Result;
                var delayTask2 = DisplayValue2(x);
                int y = delayTask2.Result;
                DateTime dtEnd = DateTime.Now;
    
                Console.Write(x + "|" + y + "|" + (dtEnd - dtBegin).TotalSeconds);
                Console.Read();
            }
    
            #region 方法一
            public static async Task<int> DisplayValue()
            //public static int DisplayValue()
            {
                int i = 1;
                int result = await Task.Run(() =>
                {
                    for (; i < 10; i++)
                    {
                        Thread.Sleep(300);
                        SqlHelper.ExecuteNonQuery("insert into TestTable select '" + i + "'");
                    }
                    return i;
                });
                return result;
            }
            #endregion
    
            #region 方法二
            public static async Task<int> DisplayValue2(int x)
            //public static int DisplayValue2()
            {
                int i = 1;
                var m = await Task.Run(() =>
                {
                    for (; i < 10; i++)
                    {
                        Thread.Sleep(x);
                        SqlHelper.ExecuteNonQuery("insert into TestTable select '" + i * 100 + "'");
                    }
                    return i;
                });
                return m;
            }
            #endregion
    
            #region 方法三
            //public static async Task DisplayValue3()
            public static void DisplayValue3()
            {
                //await Task.Run(() =>
                //{
                for (int i = 1; i < 10; i++)
                {
                    Thread.Sleep(500);
                    SqlHelper.ExecuteNonQuery("insert into TestTable select '" + i * 1000 + "'");
                }
                //});
            }
            #endregion
        }
    }
    View Code

    我的疑问:下面异步的写法有没有意义??

            public ActionResult TopMenu(string CurrentAppId)
            {
                //DisplayValue(CurrentAppId);
                return View();
            }
    
            public async Task<ActionResult> TopMenu(string CurrentAppId)
            {
                return View();
            }

     2、注意事项

      2.1、僵尸式蔓延,从底层异步,需要衍生到顶部,不要中间层又改成同步,会出现死锁现象

      2.2、多用await,少用.wait()

  • 相关阅读:
    python 的基础 学习 第六天 基础数据类型的操作方法 字典
    python 的基础 学习 第五天 基础数据类型的操作方法
    python 的基础 学习 第四天 基础数据类型
    ASP.NET MVC 入门8、ModelState与数据验证
    ASP.NET MVC 入门7、Hellper与数据的提交与绑定
    ASP.NET MVC 入门6、TempData
    ASP.NET MVC 入门5、View与ViewData
    ASP.NET MVC 入门4、Controller与Action
    ASP.NET MVC 入门3、Routing
    ASP.NET MVC 入门2、项目的目录结构与核心的DLL
  • 原文地址:https://www.cnblogs.com/takako_mu/p/5464914.html
Copyright © 2011-2022 走看看