zoukankan      html  css  js  c++  java
  • 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刷新进度条
  • 相关阅读:
    负载均衡(负载平衡)
    JavaScript中绑定事件监听函数的通用方法[ addEvent() ]
    有趣的浏览器检测
    IE6 bug之 href= “javascript:void(0);”
    SVN使用技巧 不要把不必要的文件版本化 *.suo,*.bin,*.obj
    CacheDependency缓存依赖里面的 absoluteExpiration(绝对到期时间),弹性到期时间(slidingExpiration)
    TimeSpan 和 DateTime
    字符串数组 string[] 转换为 字符串(用逗号,作为分隔符),linq Except的用法,linq获取两个字符串数组相同的部分
    List的ToLookup 分组方法
    mysql 返回查询结果,返回out返回值,多表联合查询的分页存储过程
  • 原文地址:https://www.cnblogs.com/gudaozi/p/12193392.html
Copyright © 2011-2022 走看看