public Data GetCurrent(Credentials credentials)
{
var data = new Lazy<Data>(() => GetCurrentInternal(credentials));
try
{
return data.Value;
}
catch (InvalidOperationException ex)
{
throw ex.InnerException;
}
}
如果我将通话更改为以下内容:
var data = new Task<Data>(() => GetCurrentInternal(credentials));
有什么变化吗?我应该更喜欢Task
而不是Lazy
吗?那么Dispose()
和catch(Exception)
呢?
答案 0 :(得分:11)
Lazy<T>
和Task<T>
承诺稍后会做一些工作并返回T
类型的结果。
Lazy<T>
承诺如果需要的话,尽可能晚地完成工作,并同步进行。
Task<T>
可以在您的线程执行其他工作时阻止异步工作,或阻止等待结果。
Lazy<T>
时, .Value
会冒出由lambda引起的任何异常。
Task<T>
将保留lambda引起的任何异常,并在await task
之后将其抛出。或者,如果您task.Wait()
可以将异常包装在AggregationException
中。关于捕获任务引发的异常的更多信息,我建议您参考:Catch an exception thrown by an async method和http://stiller.co.il/blog/2012/12/task-wait-vs-await/
答案 1 :(得分:11)
不,Lazy<T>
与Task<T>
不同。
Lazy<T>
是lazy evaluation概念的实现:
T
值,在首次访问时同步计算,可能会也可能不会发生。T
值,在promise 创建时计算(通常是异步),即使没有人最终实际访问它。所有这一切,Lazy<T>
和Task<T>
确实有一些你可能已经接受过的共同点。
这些类型中的每一种都是一元泛型类型,它描述了执行特定计算的唯一方式,它将产生T
值(并且该计算可以方便地作为委托传递或lambda)。换句话说,这些类型中的每一种都是monad 的示例。你可以在Stack Overflow和其他地方找到一些非常good and simple explanations of what a monad is。
答案 2 :(得分:4)
Task
和Lazy
是完全不同的概念。
您使用Task执行异步操作。一些无聊的MSDN:
Task类表示不返回a的单个操作 值通常以异步方式执行。任务对象是一个 首先是基于任务的异步模式的核心组件 在.NET Framework 4中引入。因为工作由一个 任务对象通常在线程池线程上异步执行 而不是在主应用程序线程上同步,你可以使用 Status属性,以及IsCanceled,IsCompleted和 IsFaulted属性,用于确定任务的状态。最常见的, lambda表达式用于指定任务的工作 执行。
Lazy用于延迟初始化对象。这意味着,只有在您调用lazyObj.Value
时才会初始化您的对象。
使用延迟初始化来推迟创建大型或 资源密集型对象,或资源密集型的执行 任务,特别是当这种创建或执行可能不会发生时 在该计划的整个生命周期中。
要准备延迟初始化,请创建一个Lazy实例。 您创建的Lazy对象的type参数指定了 要延迟初始化的对象的类型。构造函数 用于创建Lazy对象的确定 初始化的特征。懒惰初始化发生了 第一次访问Lazy.Value属性。