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()

  • 相关阅读:
    powershell初探(七)
    powershell初探(九)
    打造一个有感觉的Vim(一)
    屏幕录像软件Wink
    注释也精彩
    解决XP专业版局域网访问故障十八招
    可以抓文字的抓图软件
    轻松玩转XP系统(一)
    Excel实战技巧之[活用条件格式]
    局域网传输工具飞鸽传书IPMessager
  • 原文地址:https://www.cnblogs.com/takako_mu/p/5464914.html
Copyright © 2011-2022 走看看