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;
                    });
                   
            }
        }

        

原文地址:https://www.cnblogs.com/bile/p/9470025.html