C#同步调用、异步调用、异步回调、Task类、async/wait

  class AsyncClass
    {
        //声明委托
        private delegate int AddHandler(int a, int b);

        //代理方法
        public int Add(int a, int b)
        {
            Thread.Sleep(1000 * 3);
            Console.WriteLine("ThreadID--" + Thread.CurrentThread.ManagedThreadId);
            return a + b;
        }

        //同步调用,阻塞当前线程,顺序执行
        public void Tongbu()
        {
            AddHandler handler = new AddHandler(Add);
            int result = handler.Invoke(8, 5);

            Console.WriteLine(result);

            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffffff"));

            Console.WriteLine(handler(4, 5));

            Console.WriteLine("Tongbu Done!");
        }

        //异步调用
        public void Yibu()
        {
            AddHandler handler = new AddHandler(Add);

            for (int i = 1; i <= 5; i++)
            {
                //相当于另开了5个线程去执行Add方法
                IAsyncResult result = handler.BeginInvoke(i, i, new AsyncCallback(CallBack), "AsycState:OKaaa");
            }

            Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff"));

            //没有回调时也必须使用EndInvoke方法。BeginInvoke和EndInvoke必须同时出现,否则可能发生内存泄漏
            //Console.WriteLine(handler.EndInvoke(result));

            Console.WriteLine("Yibu Done!");

            Console.ReadKey();
        }

        //异步回调方法
        public void CallBack(IAsyncResult result)
        {
            //AsyncResult 是IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging
            //AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。
            AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;

            Console.WriteLine(handler.EndInvoke(result));
            Console.WriteLine(result.AsyncState);
            Console.WriteLine("CallBack Done!");
        }


        //线程池
        AutoResetEvent are = new AutoResetEvent(false); //信号灯
        int num = 10;
        public void ThreadPoolTest()
        {
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(5, 5);

            for (int i = num; i >= 0; i--)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(CallBack2),i.ToString());
            }

            Console.WriteLine("主线程执行!");

            are.WaitOne();//阻塞当前线程,直到are执行了Set方法
            Console.WriteLine("主线程结束!");
            Console.ReadKey();
        }

        //线程池回调方法
        public void CallBack2(object obj)
        {
            num--;
            Console.WriteLine(string.Format("{0}:第{1}个线程", DateTime.Now.ToString(), obj.ToString()));
            Thread.Sleep(1000);
            if (num == -1)
                are.Set();
        }


        //Task创建和运行  无返回值
        public void TaskTest()
        {
            //方式一
            Task task1 = new Task(() =>
            {
                Thread.Sleep(200);
                Console.WriteLine("void当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });
            task1.Start();

            //方式二
            Task task2 = Task.Factory.StartNew(() =>
            {
                Thread.Sleep(200);
                Console.WriteLine("void当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });

            //方式三
            Task task3 = Task.Run(() =>
            {
                Thread.Sleep(200);
                Console.WriteLine("void当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });

            Console.WriteLine("主线程 void");
            Console.WriteLine("主线程 void Done!");
        }

        //Task创建和运行  有返回值
        public void TaskReturnTest()
        {
            //方式一
            Task<string> task1 = new Task<string>(() =>
            {
                Thread.Sleep(200);
                return string.Format("当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });
            //task1.Start();

            //方式二
            Task<string> task2 = Task.Factory.StartNew<string>(() =>
            {
                Thread.Sleep(200);
                return string.Format("当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });

            //方式三
            Task<string> task3 = Task.Run<string>(() =>
            {
                Thread.Sleep(200);
                return string.Format("当前线程ID = {0}", Thread.CurrentThread.ManagedThreadId);
            });

            task1.RunSynchronously(); //阻塞主线程,直到task1线程执行完

            task2.Wait(); //等待task2执行完

            Task.WaitAll(new Task[] { task1, task2, task3 }); //等待所有task执行完

            Task.WaitAny(new Task[] { task1, task2, task3 }); //等待任何一个task执行完

            Console.WriteLine("主线程 Return");
            Console.WriteLine(task1.Result);
            Console.WriteLine(task2.Result);
            Console.WriteLine(task3.Result);

            //至少一个task执行完,去执行后续操作
            Task.WhenAny(new Task[] { task1, task2, task3 }).ContinueWith((t) =>
            {
                Console.WriteLine("至少有一个task执行完了。。。。。" );
            });

            //所有的task执行完,去执行后续操作
            Task.WhenAll(new Task[] { task1, task2, task3 }).ContinueWith((t) =>
            {
                Console.WriteLine("所有的task都执行完了。。。。。");
            });

            //等同于Task.WhenAny
            Task.Factory.ContinueWhenAny(new Task[] { task1, task2, task3 }, (t) =>
            {
                Console.WriteLine("至少有一个task执行完了。。。。。");
            });

            //等同于Task.WhenAll
            Task.Factory.ContinueWhenAll(new Task[] { task1, task2, task3 }, (t) =>
            {
                Console.WriteLine("所有的task都执行完了。。。。。");
            });

            Console.WriteLine("主线程 Return Done!");

            Console.ReadKey();
        }

        //Task取消任务,并设置取消任务后触发的事件
        public void TaskCancelTest()
        {
            CancellationTokenSource source = new CancellationTokenSource();

            //注册任务取消触发的事件
            source.Token.Register(() =>
            {
                Console.WriteLine("任务已取消");
            });
            int index = 0;
            Task task = new Task(() =>
            {
                while(!source.IsCancellationRequested)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(++index);
                }
            });
            task.Start();

            //10000毫秒后停止运行task
            source.CancelAfter(10000);

            Console.ReadKey();
        }


        //异步方法 Async、await
        public static async Task<string> GetFileContentAsync(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Open);
            var bytes = new byte[fs.Length];
            Console.WriteLine("开始读取文件");
            int len = await fs.ReadAsync(bytes, 0, bytes.Length);
            string result = Encoding.Default.GetString(bytes);
            return result;
        }

        public static async Task GetFileContentAsync2(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            var bytes = new byte[fs.Length];
            Console.WriteLine("开始读取文件");
            int len = await fs.ReadAsync(bytes, 0, bytes.Length);
            string result = Encoding.UTF8.GetString(bytes);
            return;
        }

        public static async void GetFileContentAsync3(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            var bytes = new byte[fs.Length];
            Console.WriteLine("开始读取文件");
            int len = await fs.ReadAsync(bytes, 0, bytes.Length);
            string result = Encoding.UTF8.GetString(bytes);
        }
    }

一次运行结果:

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容