zoukankan      html  css  js  c++  java
  • C# sync/async 同步/异步

    同步方法

    1             Console.WriteLine($"****************Sync Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    2             Action<string> action = this.DoSomething;
    3             for (int i = 0; i < 5; i++)
    4             {
    5                 string name = string.Format($"Sync_{i}");
    6                 action.Invoke(name); //等价 方法直接执行 this.DoSomething(name);
    7             }
    8             Console.WriteLine($"****************Sync  End  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    View Code

    异步方法

    1             Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    2             for (int i = 0; i < 5; i++)
    3             {
    4                 var name = $"Async_{i}";
    5                 action.BeginInvoke(name,null,null);
    6             }
    7             Console.WriteLine($"****************Async  End  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    View Code
     1         /// <summary>
     2         /// 一个比较耗时耗资源的私有方法
     3         /// </summary>
     4         private void DoSomething(string name)
     5         {
     6             Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
     7             long lResult = 0;
     8             for (int i = 0; i < 1_000_000; i++)
     9             {
    10                 lResult += i;
    11             }
    12             Thread.Sleep(2000);
    13             Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    14         }
    View Code

    运行上面的代码,我们发现几个问题:

    1、同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾 ;异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成

    2、同步方法慢,只有一个线程计算;

         异步多线程方法快,因为5个线程并发计算   差不多5倍,也不到5倍,CPU密集型计算(资源受限)

         多线程其实是资源换性能,1 资源不是无限的  2 资源调度损耗

    3、同步方法有序进行;

          异步多线程无序

          启动无序:线程资源是向操作系统申请的,由操作系统的调度策略决定,所以启动顺序随机

          执行时间无序:同一个任务同一个线程,执行时间也不确定,CPU分片

          结束无序:以上相加,结束也无序

    AsyncCallback 异步回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托

    AsyncState 用户定义对象:可以作为回调的参数

    1             Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    2             AsyncCallback callback = ar => Console.WriteLine($"{nameof(AsyncCallback)} 是否完成:{ar.IsCompleted} 用户定义对象:{ar.AsyncState} {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    3             for (int i = 0; i < 5; i++)
    4             {
    5                 var name = $"Async_{i}";
    6                 action.BeginInvoke(name, callback, i);
    7             }
    8             Console.WriteLine($"****************Async  End  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    View Code

    IAsyncResult 对异步调用操作的描述

    IsCompleted 判定异步任务是否完成

    while (!asyncResult.IsCompleted) //if(!asyncResult.IsCompleted)
    {
          // Do SomeThing
    }

    WaitOne 等待,即时等待  限时等待

    asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
    asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
    asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了

    EndInvoke 即时等待,而且可以获取委托的返回值 一个异步操作只能End一次

     1             Func<int, int> func = Sum;
     2             func.BeginInvoke(10, ar => {
     3                 Console.WriteLine($"线程ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")} 计算结果:{func.EndInvoke(ar)}");
     4             }, null);
     5 
     6 
     7             IAsyncResult asyncResult = func.BeginInvoke(5,ar =>
     8             {
     9                 //int iEndResultIn = func.EndInvoke(ar);
    10             }, null);
    11             int iEndResult = func.EndInvoke(asyncResult);
    View Code

    EndInvoke 可以写在BeginInvoke里也可以写在外面 但只能写一次 否则会报错

    微软文档:

    IAsyncResult:https://docs.microsoft.com/zh-cn/dotnet/api/system.iasyncresult?view=netframework-4.8

    AsyncCallback:https://docs.microsoft.com/zh-cn/dotnet/api/system.asynccallback?view=netframework-4.8

  • 相关阅读:
    siteserver学习笔记
    移动端开发适配的2中方案
    移动端中适配问题
    2倍图3倍图怎么用
    常用的网站收藏
    关于用h5实现移动端的知识梳理
    悬浮广告代码
    vue中添加echarts
    VUE中给template组件加背景
    纯CSS控制背景图片100%自适应填充布局
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11868295.html
Copyright © 2011-2022 走看看