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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容