c# 异步之async/await ,Task

使用异步的好处是什么呢?

我认为有如下好处:

1.用户体验性好

比如一个表格需要绑定大量数据,整个过程完成需要十几秒钟,而用户希望在这过程中,可以点击其它地方

(若需要界面不卡死,常用的一种方法是使用backgroundworker (实际上也是异步,新开一个线程来执行,用户体验性好了,但是实际执行效率并没有得到提升),点击按钮执行BackgroundWorker.RunWorkerAsync,触发DoWork事件)

2.提高程序执行速度

假设一个button按钮里的代码有三部分,Code1执行需要10秒,Code2执行需要20秒,Code3执行需要30秒,因为程序代码解读自上而下,传统的同步方式会等待每一句代码执行完成后,才会执行下一句代码,所以点击此button后,需要60秒才能全部执行结束,界面卡死消失;

而async/await异步的原理是Code1委托给线程1处理了,主线程不管了,程序继续往下执行,接着Code2委托给线程2执行,程序继续往下执行,接着Code3直接处理就好(不用委托异步调用),Button执行时间为最大的一部分,也就是30秒,并且界面不卡死

异步使用

async 提供上下文信息,提示编译器里面会包含await方法,async必须在返回类型之前,比如private static async Task<int>... 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class frmAsync : Form
    {
        public frmAsync()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 程序执行时间10秒
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async   void btnAsync_Click(object sender, EventArgs e)
        {
          var count= await GetCountValue(); //如果不加await,因为这是个异步方法,不会等待,变量count得到的值是int类型
          MessageBox.Show(count.ToString());
       
        }


        private async Task<int> GetCountValue()
        {

            Stopwatch sw = new Stopwatch();
            sw.Start();
            //Func<int,int> Func = Calc;
            //Func(1000);

            //Task为线程池的封装模式。
            Task<int> result = Task.Run<int>(() =>
            {
                return Calc(1000);
            });
            //方法没有参数传入,有返回值
            //Task<string> result2 = Task.Run<string>
            //    (() => { return GetCalc(); });


            //await result2;

            int finialValue = 0;
            int countValue = 0;
            //可以在匿名函数里面直接写方法体
            //Task<int> result2 = Task.Run<int>(() =>
            //{

            //    for (int i = 0; i < 1000; i++)
            //    {
            //        System.Threading.Thread.Sleep(10);
            //        countValue += i;
            //    }
            //    return countValue;

            //});

            //直接执行
                for (int i = 0; i < 1000; i++)
                {
                    System.Threading.Thread.Sleep(10);
                    countValue += i;
                }

            await result;
           // await result2;

            #region 这样写耗时一样,但是界面会卡死,直到运行结束
            //Task[] para = { result, result2 };
            //Task.WaitAll(para);
            #endregion


            finialValue = countValue + result.Result;

            sw.Stop();
            this.richTextBox1.Text = "最终计算结果:" + finialValue + "异步方法耗时:" + (sw.ElapsedMilliseconds / 1000) + "";

            return finialValue;

        }



        /// <summary>
        /// 传统的同步方式,程序执行时间叠加,这里为20秒,
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTongbu_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
          

            int countValue = 0;
            int finialValue = 0;

            int value1 = Calc(1000);
            //这段代码体现出winForm是单线程的,我们期望会在执行10秒后,界面上先出现如下提示,在实际执行的时候发现,
            //会与最终计算结果....的文本值一起出现在richTextBox1上,
            //虽然 Calc(1000)的值计算出来了,但是线程很忙,紧接着在执行下一段代码,没有空去更新richTextBox1控件
            
            this.richTextBox1.Text = "第一阶段值:" + value1.ToString();
            for (int i = 0; i < 1000; i++)
            {
                System.Threading.Thread.Sleep(10);
                countValue += i;
            }
            finialValue = value1 + countValue;
            sw.Stop();
            this.richTextBox1.Text += "最终计算结果:" + finialValue + "同步方法耗时:" + (sw.ElapsedMilliseconds / 1000) + "";
        }


        private int Calc(int maxNum)
        {
            int sumValue = 0;
            for (int i = 0; i < maxNum; i++)
            {
                System.Threading.Thread.Sleep(10);
                sumValue += i;
            }
            return sumValue;

        }

      
        private static string GetCalc()
        {
            //Thread.Sleep(10000);
            int a = 1000;
            double b = 0;
            for (int i = 0; i < a; i++)
            {
                System.Threading.Thread.Sleep(10);
                b += i;
            }
            return b.ToString();
        }
        /// <summary>
        ///  Task.Factory.StartNew 程序执行时间20秒
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button1_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            int countValue = 0;
            Task<int> result = Task.Factory.StartNew<int>(() => { return Calc(1000); }).ContinueWith(ts =>
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        System.Threading.Thread.Sleep(10);
                        countValue += i;
                    }
                    return countValue + ts.Result;

                });
            // Task.WaitAll(result);
            await result;

            sw.Stop();
            this.richTextBox1.Text = "最终计算结果:" + result.Result + "异步方法耗时:" + (sw.ElapsedMilliseconds / 1000) + "";
        }
        /// <summary>
        /// 委托的异步调用,界面不能点击,程序执行时间10S
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async  void button2_Click(object sender, EventArgs e)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Func<int, int> Func = Calc;
            IAsyncResult AsyncResult = Func.BeginInvoke(1000, null, null);
            int finialValue = 0;
            int countValue = 0;
            Func<int> Func2 = (() =>
            {

                for (int i = 0; i < 1000; i++)
                {
                    System.Threading.Thread.Sleep(10);
                    countValue += i;
                }
                return countValue;

            });

            IAsyncResult AsyncResult2 = Func2.BeginInvoke(null, null);

            int value1 = Func.EndInvoke(AsyncResult);
            int value2 = Func2.EndInvoke(AsyncResult2);

            finialValue = value1 + value2;

            sw.Stop();
            this.richTextBox1.Text = "最终计算结果:" + finialValue + "BeginInvoke异步方法耗时:" + (sw.ElapsedMilliseconds / 1000) + "";
        }
       

    }
}
Async/await Task
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class frmBackgroundworker : Form
    {


        BackgroundWorker bgWorker = new BackgroundWorker();


        public frmBackgroundworker()
        {
            InitializeComponent();
            bgWorker.WorkerReportsProgress = true;
            bgWorker.WorkerSupportsCancellation = true;

            bgWorker.DoWork += bgWorker_DoWork;
            bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
            bgWorker.ProgressChanged += bgWorker_ProgressChanged;

        }



        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                this.lblInfo.Text = "用户已取消";
                return;
            }
            if (e.Error != null)
            {
                this.lblInfo.Text = e.Error.Message;
                return;
            }
            this.lblInfo.Text = e.Result.ToString();

        }

        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = sender as BackgroundWorker;

            for (int i = 1; i <= 100; i++)
            {
                if (bw.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                System.Threading.Thread.Sleep(20);
                bw.ReportProgress(i, string.Format("当前完成进度{0}%", i));
            }
            System.Threading.Thread.Sleep(1000);
            e.Result = "执行完成";

        }

        void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
            this.lblInfo.Text = e.UserState.ToString();

        }

        private void btn_Start_Click(object sender, EventArgs e)
        {
            try
            {
                bgWorker.RunWorkerAsync();
            }
            catch (Exception ex)
            {


            }
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            try
            {
           
                bgWorker.CancelAsync();
            }
            catch (Exception)
            {

                throw;
            }
        }

       
    }
}
BackgroundWorker刷新进度条

猜你喜欢

转载自www.cnblogs.com/gudaozi/p/12193392.html