异步返回类型

在上篇文章我们简要认识了异步编程后,本章则要我们对异步的返回类型进行一定的了解和认识。 


         异步方法可以具有以下返回类型(常用):

Task返回类型 (对于执行操作但不返回任何值的异步方法)

Task<TResult> 返回类型 (对于返回值的异步方法)

Void 返回类型 (对于事件处理程序)


Task返回类型

Task返回类型是不包含 return 语句的异步方法或包含不返回操作数的 return 语句的异步方法。如果在异步方法中使用 Task 返回类型,调用方法可以使用 await 运算符暂停调用方的完成,直至被调用的异步方法结束。

 public static async Task DisplayCurrentInfoAsync()
        {
            await WaitAndApologizeAsync();

            Console.WriteLine($"今天日期是: {DateTime.Now:D}");
            Console.WriteLine($"当前时间为: {DateTime.Now.TimeOfDay:t}");
            Console.WriteLine("今天是晴天");
        }

        static async Task WaitAndApologizeAsync()
        {
            await Task.Delay(2000);

            Console.WriteLine("当前网络不好,请稍后再试\n");
        }
        // 输出:
        //    当前网络不好,请稍后再试
        //
        //    今天日期是 2022-6-8
        //    当前时间为: 12:09:24.2183304
        //    今天是晴天

Task<TResult> 返回类型

Task<TResult> 返回类型就是包含 return 语句的异步方法,其中操作数是 TResult,操作数可以简单理解成一个泛型占位符。

 public static async Task ShowTodaysInfoAsync()
        {
            string message = $"今天是: {DateTime.Today:D}\n" + "今天学习时间: " + $"{await GetLeisureHoursAsync()} 小时";
            Console.WriteLine(message);
        }

        static async Task<int> GetLeisureHoursAsync()
        {
            DayOfWeek today = await Task.FromResult(DateTime.Now.DayOfWeek);
            int leisureHours = today is DayOfWeek.Saturday || today is DayOfWeek.Sunday ? 16 : 5;
            return leisureHours;
        }
        // 输出:
        //    今天是: 2022-6-8
        //    今天学习时间:  5 小时

Void 返回类型

在异步事件处理程序中使用 void 返回类型,这需要 void 返回类型。 而这里的返回类型是指对于事件处理程序以外的不返回值,应返回 Task。此类方法的任何调用方都必须继续完成,而无需等待调用的异步方法完成。 调用方必须独立于异步方法生成的任何值或异常。

参考案例如下,均有注释说明:

 #region 生成一个点击事件Click()
        public class NaiveButton
        {
            public event EventHandler Clicked;

            public void Click()
            {
                Console.WriteLine("提出请求");
                Clicked?.Invoke(this, EventArgs.Empty);//Invoke调用,为下面MultipleEventHandlersAsync方法提供新增调用
                Console.WriteLine("通知监听器");
            }
        } 
        #endregion
        public class AsyncVoidExample
        {
            static readonly TaskCompletionSource<bool> s_tcs = new TaskCompletionSource<bool>();

            public static async Task MultipleEventHandlersAsync() //创建一个Task异步方法
            {
                Task<bool> secondHandlerFinished = s_tcs.Task;

                var button = new NaiveButton();//new 一个button对象

                //将下列的OnButtonClicked1、OnButtonClicked2Async、OnButtonClicked3的方法逐一新增到button对象里
                button.Clicked += OnButtonClicked1;
                button.Clicked += OnButtonClicked2Async;
                button.Clicked += OnButtonClicked3;

                Console.WriteLine("Click()方法被调用前");
                button.Click();//触发Click()点击事件(输出案例在底端)
                Console.WriteLine("Click()方法被调用后");

                await secondHandlerFinished;
            }

            private static void OnButtonClicked1(object sender, EventArgs e)
            {
                Console.WriteLine("   程序1启动中。。。");
                Task.Delay(100).Wait();
                Console.WriteLine("   程序1结束");
            }

            private static async void OnButtonClicked2Async(object sender, EventArgs e)
            {
                Console.WriteLine("   程序2启动中。。。");
                Task.Delay(100).Wait();
                Console.WriteLine("   程序2异步处理中");

                /*await等待Task执行延时0.5秒后输出,也对应“此类方法的任何调用方都必须继续完成,而无需等待调用的异步方法完成。”*/
                await Task.Delay(500);
                Console.WriteLine("   程序2结束");

                s_tcs.SetResult(true);
                
            }

            private static void OnButtonClicked3(object sender, EventArgs e)
            {
                Console.WriteLine("   程序3启动中。。。");
                Task.Delay(100).Wait();
                Console.WriteLine("   程序3结束");
            }
        }
        // 输出:
        //
        // 点击按钮,Click()方法被调用前
        //    提出请求
        //    程序1启动中。。。
        //    程序1结束
        //    程序2启动中。。。
        //    程序2异步处理中
        //    程序3启动中。。。
        //    程序3结束
        // 通知监听器
        // 点击按钮,Click()方法被调用后
        //    程序2结束 

最后再附带一个小技巧:当遇到微软封装好的类/方法不懂怎么使用时,选中它,按F12跳转进去就会看到里面的构造,里面都有解释说明(不出意外都是英文)。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows 应用程序编程中常见的一个模式就是,在GUI用户界面下,将耗时的文件和网络处理放入 子线程,以避免用户界面不能响应的问题。在.NET出现以前,创建线 程并监视线程结束,还要更新 界面等工作,即复杂又要手写大量代码,并且难以调试。在.NET中,程序员可以通过异步调用,使 用简单的代码完成这项工作。 .NET Framework允许异步调用任何方法。使用异步调用之前,要定义一个委托,它的方法签名要与 调用方法签名一致。.NET会自动产生此委托的BeginInvoke和EndInvoke方法。 BeginInvoke 方法用于启动异步调用。它除了具有调用方法相同的参数外,还附加了两个额外的参 数,这两个额外参数将用于回调方法。 BeginInvoke执行后立即返回,并不等待异步调用完成。 BeginInvoke返回一个IAsyncResult接口,它可以用于监视调用的进度。EndInvoke方法被用来获取 异步调用的结果。在 BeginInvoke执行以后,任何时间都可以调用EndInvoke。如果异步调用尚未完 成,EndInvoke会被阻塞,直到异步调用完成。EndInvoke带有一个IAsyncResult接口类型的参数, 并返回一个IAsyncResult接口,用来获取调用结果。 本文中的代码演示了使用BeginInvoke和EndInvoke进行异步调用的四种常见调用方式。在调用 BeginInvoke之后,您可以: 1.完成一些其它工作,然后调用EndInvoke,等待异步调用完成。 2.使用IAsyncResult.AsyncWaitHandle获取一个WaitHandle,使用它的WaitOne方法执行阻塞调 用,完成后再调用EndInvoke。 3.轮询BeginInvoke返回的IAsyncResult接口,在异步调用完成后,再调用EndInvoke。 4.给BeginInvoke传递一个回调方法的委托,异步调用完成后,这个回调方法会在ThreadPool线程 上执行,可以在这个方法内调用EndInvoke。 警告:异步调用完成后,必须调用EndInvoke。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值