[AaronYang]C#人爱学不学8-异步接口与.net4.5的进度报告

异步签名async在接口的使用   

因为async签名不能修饰接口的,那如何返回值?我们使用Task.FromResult<T>

Image 2.png

新建接口,并实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace wpf_bing1
{
    interface ITestAsyncInterface
    {
        Task<string> GetAuthorAsync();
    }

    class TestAsyncImpl : ITestAsyncInterface
    {
        public  Task<string> GetAuthorAsync()
        {
            return Task.FromResult<string>("hello ay");
        }
    }


}

测试代码

      private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            Task.Run(() =>
                             {
                                 ITestAsyncInterface testinterface = new TestAsyncImpl();
                                 Task<string> interfaceResult = testinterface.GetAuthorAsync();
                                 MessageBox.Show(interfaceResult.Result);
                             });
        }

在用同步代码实现异步接口时候,要避免使用任何形式的阻塞操作。Task.FromResult只能提供结果正确的同步Task对象。如果要让返回的task对象有一个其他类型的结果(例如NotImplementedException结束的Task对象),就得自行创建使用TaskCompletionSource的辅助方法。

TaskCompletionSource<T>类有很多Task的返回方式,FromResult<T>是它其中的一个简写

也就是上面的代码可以这样写

        public Task<string> GetAuthorAsync()
        {
            var tcs = new TaskCompletionSource<string>();
            tcs.SetResult("Hello ay");
            return tcs.Task;
        }

那么如何返回其他的呢,我也是第一次学,看它给我们提供了什么属性或者方法

Image 3.png

我们返回一个异常

   static Task<T> NotImplementedAsync<T>() {
            var tcs = new TaskCompletionSource<T>();
            tcs.SetException(new NotImplementedException());
            return tcs.Task;
        }

然后调用

   public Task<string> GetAuthorAsync()
        {
            //var tcs = new TaskCompletionSource<string>();
            //tcs.SetResult("Hello ay");
            //return tcs.Task;

            //无法获得,返回一个为实现
            return NotImplementedAsync<string>();
        }

前台添加个按钮,加上单击事件

Image 4.png

所以你在 上面可以创建一个默认的 Task或者Task<T>返回

       private static readonly Task<string> defaultStringTask = Task.FromResult<string>("没有实现哦,亲,可以登录www.ayjs.net查看更多教程");

异步操作 返回进度,使用IProgress<T>和Progress<T>类型

先来个先简单的double报告进度。pb_ayjs_1是前台的进度条name

        /// <summary>
        /// 开始工作
        /// </summary>
        /// <returns></returns>
         async Task StartWork()
        {
            var progress = new Progress<double>();
            progress.ProgressChanged += (sender, args) =>
            {
                pb_ayjs_1.Value = args;
            };
            await Working(progress);
        }

添加working的异步方法,模拟延时操作

       /// <summary>
        /// 工作中
        /// </summary>
        /// <param name="progress"></param>
        /// <returns></returns>
        async Task Working(IProgress<double> progress = null)
        {
            //处理耗时任务
            for (int i = 1; i <=10; i++)
            {
                await Task.Delay(TimeSpan.FromMilliseconds(new Random().Next(20,1000)));
                //报告进度
                if (progress != null)
                {
                    progress.Report((i / 10.00) * 100);
                }
            }
        }

调用的时候,这里没有用Task.Run了,因为StartWork中用到了UI线程的东西pb_ayjs_1,就是进度条,如果使用了Task.Run,就会报错,说对象被某某线程占用。线程都有个当前环境

    private void Button_Click_5(object sender, RoutedEventArgs e)
        {
                Task createItem = StartWork();
        }

效果图:

5.gif

发现后台在进行耗时操作的时候,并没有卡顿,界面是响应的,这就是异步操作。

当然你也可以新建一个进度报告实体,例如下面

    public class ProgressResult
    {
        public int Current { get; set; }
        public int Total { get; set; }
    }

那么在Process<T>的T参数就是这个类型,而ProgressChanged的args参数也就是这个对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值