频道栏目
读书频道 > 软件开发 > C# > C#并发编程经典实例
2.2 返回完成的任务
2014-12-06 13:46:31     我来说两句
收藏   我要投稿

本文所属图书 > C#并发编程经典实例

本书全面讲解C 并发编程技术,侧重于 NET 平台上较新、较实用的方法。全书分为几大部分:首先介绍几种并发编程技术,包括异步编程、并行编程、TPL 数据流、响应式编程;然后阐述一些重要的知识点,包括测试技  立即去当当网订购

问题

如何实现一个具有异步签名的同步方法。如果从异步接口或基类继承代码,但希望用同步的方法来实现它,就会出现这种情况。对异步代码做单元测试,以及用简单的生成方法存根(stub)或者模拟对象(mock)来产生异步接口,这两种情况下都可使用这种技术。

解决方案

可以使用Task.FromResult 方法创建并返回一个新的Task<T> 对象,这个Task 对象是已经完成的,并有指定的值。

interface IMyAsyncInterface
{
Task<int> GetValueAsync();
}
class MySynchronousImplementation : IMyAsyncInterface
{
public Task<int> GetValueAsync()
{
return Task.FromResult(13);
}
}

如果使用了Microsoft.Bcl.Async,FromResult 方法就在TaskEx 类中。

讨论

在用同步代码实现异步接口时,要避免使用任何形式的阻塞操作。在异步方法中进行阻塞操作,然后返回一个完成的Task 对象,这种做法并不可取。作为一个反例,我们来看一下.NET 4.5 中Console 类的文本读取器。

Console.In.ReadLineAsync 一定会阻塞调用它的线程,直到它读取完一行文字,然后会返回一个已完成的Task 对象。这种实现方式并不直观,很多开发人员也觉得很奇怪。一旦异步方法阻塞,调用它的线程就无法启动其他任务,这会干扰程序的并发性,甚至可能产生死锁。

Task.FromResult 只能提供结果正确的同步Task 对象。如果要让返回的Task 对象有一个其他类型的结果(例如以NotImplementedException 结束的Task 对象),就得自行创建使用TaskCompletionSource 的辅助方法:

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

从概念上讲,Task.FromResult 只不过是TaskCompletionSource 的一个简化版本,它与上面的代码非常类似。

如果用Task.FromResult 反复调用同一参数,则可考虑用一个实际的task 变量。例如,可以一次性建立一个结果为0 的Task<int> 对象,在以后的调用中就不需要创建额外的实例了,这样可减少垃圾回收的次数:

private static readonly Task<int> zeroTask = Task.FromResult(0);
static Task<int> GetValueAsync()
{
return zeroTask;
}

参阅

6.1 节介绍异步方法的单元测试。

10.1 节介绍async 方法的继承。
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:2.1 暂停一段时间
下一篇:2.3 报告进度
相关文章
图文推荐
排行
热门
最新书评
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站