• 同步函数的异步化


    先说下异步(Asynchronous)和多线程(Multi-threading)的区别:异步是相对与同步来说的,一般来说意味着非阻塞;异步在具体实现上是用多线程来实现的,但好处是你不用操心和管理多线程,它给你封装了一个干净的接口来调用。当然,在linux和javascript环境下,你要理解异步一般要理解事件驱动机制/Event loop: 《理解Event loop》。这里讲的主要是.NET。同步函数异步化有很多好处,但异步化是有开销的:《Understanding the Costs of Async and Await》。具体来说,下列场合适合用异步化:

    • 耗时的I/O操作,例如:读文件I/O,访问网络资源网络I/O….
    • 耗时的CPU的操作:建议配合多线程,例如Task.Factory启动新的线程,在线程里面进行异步访问

    举例,这里有个同步方法Process(例子不太恰当,应该是耗时的I/O操作的例子比较好)

    public class Test
    {
       public int Process(int a)
       {
           System.Threading.Thread.Sleep(3000);
           return a + 1;
       }
    }

    现在把这个同步方法改造为异步方法:

    namespace ConsoleApplication6
    {
        public class Test
        {
            public int Process(int a)
            {
                System.Threading.Thread.Sleep(3000);
                return a + 1;
            }
    
            public void ProcessAsync(int a, Action<int> callBackAction)
            {
                Func<int> func = () =>
                {
                    System.Threading.Thread.Sleep(3000);
                    return a + 1;
                };
                func.BeginInvoke((ar) =>
                {
                    var result = func.EndInvoke(ar);
                    callBackAction.Invoke(result);
                },
                    null);
            }
        }
    }    

    测试方法:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication6
    {
        class Program
        {
            static void Main(string[] args)
            {
                var tester = new Test();
                
                Console.WriteLine("Sync start");
                var result1 = tester.Process(1);
                Console.WriteLine("Sync finish: " + result1);
    
                Console.WriteLine("Async start");
                tester.ProcessAsync(2, (r) =>
                {
                    Console.WriteLine("Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
                Console.WriteLine("Async continue" + " thread id: " +
                                  System.Threading.Thread.CurrentThread.ManagedThreadId);
    
    
                Console.Read();
            }
        }
    }

    输出结果:

    Sync start
    (wait 3 seconds)
    Sync finish: 2
    Async start
    Async continue
    (wait 3 seconds)
    Async finish: 3

    如果多加几个操作,看看起了几个线程:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication6
    {
        class Program
        {
            static void Main(string[] args)
            {
                var tester = new Test();
                
                Console.WriteLine("Sync start");
                var result1 = tester.Process(1);
                Console.WriteLine("Sync finish: " + result1);
    
                Console.WriteLine("Async start");
                tester.ProcessAsync(2, (r) =>
                {
                    Console.WriteLine("Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
                Console.WriteLine("Async continue" + " thread id: " +
                                  System.Threading.Thread.CurrentThread.ManagedThreadId);
    
    
    
                Console.WriteLine("Async start");
                tester.ProcessAsync(2, (r) =>
                {
                    Console.WriteLine("Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
                Console.WriteLine("Async continue" + " thread id: " +
                                  System.Threading.Thread.CurrentThread.ManagedThreadId);
    
    
                Console.WriteLine("Async start");
                tester.ProcessAsync(2, (r) =>
                {
                    Console.WriteLine("Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
                Console.WriteLine("Async continue" + " thread id: " +
                                  System.Threading.Thread.CurrentThread.ManagedThreadId);
    
    
                Console.WriteLine("Async start");
                tester.ProcessAsync(2, (r) =>
                {
                    Console.WriteLine("Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
                Console.WriteLine("Async continue" + " thread id: " +
                                  System.Threading.Thread.CurrentThread.ManagedThreadId);
    
                Console.Read();
            }
        }
    }

    输出:

    Sync start
    Sync finish: 2
    Async start
    Async continue thread id: 9
    Async start
    Async continue thread id: 9
    Async start
    Async continue thread id: 9
    Async start
    Async continue thread id: 9
    Async finish: 3 thread id: 13
    Async finish: 3 thread id: 11
    Async finish: 3 thread id: 10
    Async finish: 3 thread id: 12

    说明背后是用了多线程。

    现在我们再用async和await关键字来改造一下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication6
    {
        public class Test
        {
            public void ProcessAsync(int a, Action<int> callBackAction)
            {
                Func<int> func = () =>
                {
                    System.Threading.Thread.Sleep(3000);
                    return a + 1;
                };
                func.BeginInvoke((ar) =>
                {
                    var result = func.EndInvoke(ar);
                    callBackAction.Invoke(result);
                },
                    null);
            }
    
            public Task<int> TaskProcessAsync(Action<int> callBackAction)
            {
                var tcs = new TaskCompletionSource<int>();
                ProcessAsync(3, (r) =>
                {
                    callBackAction.Invoke(r);
                });
                return tcs.Task;
            }
    
            public async Task<int> QueryProcess(Action<int> callBackAction)
            {
                int i = await TaskProcessAsync(callBackAction);
                return i;
            }
    
        }
        
        public class Class1
        {
            public async Task<int> Test()
            {
                var tester = new Test();
    
                var i = await tester.QueryProcess((r) =>
                {
                    Console.WriteLine("await Async finish: " + r + " thread id: " +
                                      System.Threading.Thread.CurrentThread.ManagedThreadId);
                });
    
                return i;
            }
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                var t = new Class1();
                t.Test();
    
                Console.Read();
            }
        }
    }
  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/Mainz/p/3532203.html
Copyright © 2020-2023  润新知