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

https://www.cnblogs.com/bile/p/9470025.html

複製代碼

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

複製代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章