隐藏

在C#中阻塞与不阻塞async和await用法

发布:2022/12/29 10:50:37作者:管理员 来源:本站 浏览次数:604

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就是异步,加了就同步处理


方法前面加个async,表明这个方法是多线程的,是异步的,主线程或调用该方法多线程不会等待方法结束,除非在调用的时候加awite等待..


实例测试:


private  void button1_Click(object sender, EventArgs e)

       {

           textBox1.Text = "start\r\n";

           aaa();//异步方法,如果里面有awits的时候启动异步,执行下一条代码=====>>"textBox1.Text += "dfgfdgdfdfg\r\n";"

           textBox1.Text += "dfgfdgdfdfg\r\n";

       }

     

       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 + "\r\n";

           }

           textBox1.Text += "11111111111111111111\r\n";

           while (plist.Count>0)

           {

               try

               {

                   Task<PP> imageTask = await Task.WhenAny(plist);

                   plist.Remove(imageTask);


                   PP pppppp = await imageTask;

                   textBox1.Text += pppppp.Name + "\r\n";

                   

               }

               catch (Exception exc) { MessageBox.Show(exc.Message); }


           }

           textBox1.Text += "22222222222222222222\r\n";

       }

       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;

                   });

                 

           }

       }