C# 异步编程全面解析
作者:网络转载 发布时间:[ 2015/6/29 17:34:39 ] 推荐标签:软件开发 C#
Tasks
Task和Task<T>类型已经存在于.NET Framework 4.0中,一个Task代表一个进行时的活动,它可能是一个运行在单独线程中的一个CPU密集型的工作或者一个IO操作,手动的创建一个不工作在单独线程的任务也是非常容易的:
static Task ReadFileAsync(string filePath,out byte[]buffer)
{
Stream stream=File.Open(filePath,FileMode.Open);
buffer=new byte[stream.Length];
var tcs=new TaskCompletionSource<double>();
stream.BeginRead(buffer,0,buffer.Length,arr=>
{
var length=stream.EndRead(arr);
tcs.SetResult(stream.Length);
},null);
return tcs.Task;
}
一旦创建了一个TaskCompletionSource对象,你可以返回与它关联的Task对象,问相关的工作完成后,客户代码才得到终的结果,这时Task没有占据自己的线程。
如果实际任务失败,Task从样可以携带异常并且向上传播,如果使用await将触发客户端代码的异常:
static async void ReadAssignedFile()
{
byte[]buffer;
try
{
double length=await ReadFileAsync("SomeFileDoNotExisted.txt",out buffer);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static Task<double>ReadFileAsync(string filePath,out byte[]buffer)
{
Stream stream=File.Open(filePath,FileMode.Open);
buffer=new byte[stream.Length];
var tcs=new TaskCompletionSource<double>();
stream.BeginRead(buffer,0,buffer.Length,arr=>
{
try
{
var length=stream.EndRead(arr);
tcs.SetResult(stream.Length);
}
catch(IOException ex)
{
tcs.SetException(ex);
}
},null);
return tcs.Task;
}
image
基于任务的异步编程模型
上文中解释了异步方法应该是的样子-Task-based asynchronous Pattern(TAP),上文中异步的体现只需要一个调用方法和异步异步方法,后者返回一个Task或者Task<T>。
下文中将介绍一些TAP中的约定,包括怎么处理“取消”和“进行中”,我们将进一步讲解基于任务的编程模型。
Async和await
理解async方法不运行在自己的线程是非常重要的,事实上,编写一个async方法但是没有任何await的话,它将会是一个不折不扣的同步方法:
static async Task<int>TenToSevenAsync()
{
Thread.Sleep(10000);
return 7;
}
假如你调用这个方法,将会阻塞线程10秒后返回7,这也许不是你期望的,在VS中也将得到一个警告,因为这可能永远不是想要的结果。
只有一个async方法运行到一个await语句时,它才立即把控制权返回给调用方,然而只有当等待的任务完成之后,它才会真正的返回结果,这意味着你需要确保async方法中的代码不会做过多的任务或者阻塞性能的调用。下面的实例才是你所期望的效果
static async Task<int>TenToSevenAsync()
{
await Task.Delay(3000);
return 7;
}
Task.Delay实际上是异步版本的Tread,Sleep,它返回一个Task,这个Task将会在指定的时间内完成。
时间处理程序和无返回值的异步方法
异步方法可以从其他异步方法使用await创建,但是异步在哪里结束?
在客户端程序中,通常的回答是异步方法由事件发起,用户点击一个按钮,一个异步方法被激活,直到它完成,事件本身并不关系方法何时执行完成。这是通常所说的“发后既忘”
为了适应这种模式,异步方法通常明确的被设计为“发后既忘”-使用void作为返回值替代Task<TResult>类型,这让方法可以直接作为一个事件处理程序。当一个void saync的方法执行时,没有Task被返回,调用者也无法追踪调用是否完成。
private async void someButton_Click(object sender,RoutedEventArgs e)
{
someButton.IsEnabled=false;
await SumPageSizesAsync(GetUrls()));
someButton.IsEnabled=true;
}
结束语
越写到后,越不说人话啦。。。。。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11