异步签名async在接口的使用
因为async签名不能修饰接口的,那如何返回值?我们使用Task.FromResult<T>
新建接口,并实现
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; }
那么如何返回其他的呢,我也是第一次学,看它给我们提供了什么属性或者方法
我们返回一个异常
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>(); }
前台添加个按钮,加上单击事件
所以你在 上面可以创建一个默认的 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(); }
效果图:
发现后台在进行耗时操作的时候,并没有卡顿,界面是响应的,这就是异步操作。
当然你也可以新建一个进度报告实体,例如下面
public class ProgressResult { public int Current { get; set; } public int Total { get; set; } }
那么在Process<T>的T参数就是这个类型,而ProgressChanged的args参数也就是这个对象