• c# async和await 用法(阻塞与不阻塞)


    void PagePaint()
    {
        Console.WriteLine("Paint Start");
        Paint();
        Console.WriteLine("Paint End");
    }
    
    void Paint()
    {
        Rendering("Header");
        Rendering(RequestBody());
        Rendering("Footer");
    }
    
    string RequestBody()
    {
        Thread.Sleep(1000);
        return "Body";
    }

    假设有这么个页面布局的方法,依次对头部、主体和底部进行渲染,头部和底部是固定的内容,而主体需要额外请求。
    这里用Sleep模拟网络延时,Rendering方法其实也就是对Console.WriteLine的简单封装而已。。。
    PagePaint运行过后,结果是这样的:

    Paint Start
    Header
    Body
    Footer
    Paint End

    挺正常的结果,但是Header渲染完以后页面就阻塞了,这个时候用户没法对Header进行操作。
    于是就进行这样的修正:

    async void Paint()
    {
        Rendering("Header");
        Rendering(await RequestBody());
        Rendering("Footer");
    }
    
    async Task<string> RequestBody()
    {
        return await Task.Run(() =>
        {
            Thread.Sleep(1000);
            return "Body";
        });
    }

    运行结果变成了这样:

    Paint Start
    Header
    Paint End
    Body
    Footer

    这样就能在Header出现之后不阻塞主线程了。

    不过呢,Footer一直都得等到Body渲染完成后才能被渲染,这个逻辑现在看来还没问题,因为底部要相对于主体进行布局。
    然而我这时候又想给页面加一个广告,而且是fixed定位的那种,管啥头部主体想盖住就盖住,你们在哪它不管。
    比如这样写:

    async void Paint()
    {
        Rendering(await RequestAds());
        Rendering("Header");
        Rendering(await RequestBody());
        Rendering("Footer");
    }

    出现了很严重的问题,头部都得等广告加载好了才能渲染,这样显然是不对的。
    所以应该改成这样:

    async void Paint()
    {
        PaintAds();
        Rendering("Header");
        Rendering(await RequestBody());
        Rendering("Footer");
    }
    
    async void PaintAds()
    {
        string ads = await Task.Run(() =>
        {
            Thread.Sleep(1000);
            return "Ads";
        });
        Rendering(ads);
    }

    这样的运行结果就算令人满意了:

    Paint Start
    Header
    Paint End
    Ads
    Body
    Footer

     总结:

           1.Paint()加async表示是可异步的,当里面有awit的时候,调用Paint的线程会异步处理Paint()后面的代码

           2.Paint()里面是同步的,想要实现异步效果,再嵌套个加async的异步方法.

            总之async 不加awit就是异步,加了就同步处理

    实例测试:

       private  void button1_Click(object sender, EventArgs e)
            {
                textBox1.Text = "start
    ";
                aaa();//异步方法,如果里面有awits的时候启动异步,执行下一条代码=====>>"textBox1.Text += "dfgfdgdfdfg
    ";"
                textBox1.Text += "dfgfdgdfdfg
    ";
            }
           
            public async void aaa()
            {
                List<Task<PP>> plist = new List<Task<PP>>();
                for (int i = 0; i < 10; i++)
                {
                    Task<PP> p = Getp(i);
                    // p.Start();
                    plist.Add(p);
                    //PP p = await Getp(i);
                    //textBox1.Text +=p.Name + "
    ";
                }
                textBox1.Text += "11111111111111111111
    ";
                while (plist.Count>0)
                {
                    try
                    {
                        Task<PP> imageTask = await Task.WhenAny(plist);
                        plist.Remove(imageTask);
    
                        PP pppppp = await imageTask;
                        textBox1.Text += pppppp.Name + "
    ";
                        
                    }
                    catch (Exception exc) { MessageBox.Show(exc.Message); }
    
                }
                textBox1.Text += "22222222222222222222
    ";
            }
            public async Task<PP> Getp(int index)
            {
                PP p=new PP ();
                switch (index)
                {
                    case 1:
                        
                               Thread.Sleep(1000);
                               p.Index=index;
                               p.Name=index.ToString();
                               return p;
                      
                       
                    case 2:
                        return await Task.Run(() =>
                        {
                            Thread.Sleep(100);
                            p.Index = index;
                            p.Name = index.ToString();
                            return p;
                        });
                    case 3:
                        return await Task.Run(() =>
                        {
                            Thread.Sleep(1000);
                            p.Index = index;
                            p.Name = index.ToString();
                            return p;
                        });
                    case 4:
                        return await Task.Run(() =>
                        {
                            Thread.Sleep(500);
                            p.Index = index;
                            p.Name = index.ToString();
                            return p;
                        });
                    default:
                        return await Task.Run(() =>
                        {
                            Thread.Sleep(2000);
                            p.Index = index;
                            p.Name = index.ToString();
                            return p;
                        });
                       
                }
            }

            

  • 相关阅读:
    架构思维—软件架构—系统架构—系统—大局观、系统观(结构与秩序)、还原论(分与合)
    微核架构的本质是微核掌握了更多的上下文-----微核架构 = 整体上下文 + 配置组成
    spring mvc的工作流程
    @getMapping和@postMapping,@RestController
    springTransaction Management
    Architecture of Spring Framework
    Tomcat 6 —— Realm域管理
    Tomcat模型结构
    spring的启动过程
    ServletContext、webApplicationContext、DispatcherServlet与容器
  • 原文地址:https://www.cnblogs.com/bile/p/9470025.html
Copyright © 2020-2023  润新知