Tag: 任务

如果它没有抛出,则从工厂方法缓存结果

更新:@usr指出我错误地认为Lazy的默认线程安全模式是LazyThreadSafetyMode.PublicationOnly …后严重修改… 我想懒惰地通过async工厂方法计算一个值(即它返回Task )并在成功时缓存它。 在例外情况下,我想让我可以使用它。 但是,我不想成为Lazy在其默认模式下具有的exception缓存行为 ( LazyThreadSafetyMode.ExecutionAndPublication ) exception缓存:使用工厂方法时,会缓存exception。 也就是说,如果工厂方法在线程第一次尝试访问Lazy对象的Value属性时抛出exception,则每次后续尝试都会抛出相同的exception。 这确保了对Value属性的每次调用都会产生相同的结果,并避免在不同的线程获得不同结果时可能出现的细微错误。 懒惰代表一个实际的T,否则它将在某个早期点(通常在启动期间)初始化。 在那个早期点失败通常是致命的。 如果存在可恢复故障的可能性,我们建议您将重试逻辑构建到初始化例程(在本例中为工厂方法),就像您没有使用延迟初始化一样。 Stephen Toub有一个AsyncLazy类和AsyncLazy似乎恰到好处: public class AsyncLazy : Lazy<Task> { public AsyncLazy(Func<Task> taskFactory) : base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap()) { } public TaskAwaiter GetAwaiter() { return Value.GetAwaiter(); } } 然而,这与默认的Lazy实际上是相同的行为 – 如果出现问题,则不会重试。 我正在寻找与Lazy(Func, LazyThreadSafetyMode.PublicationOnly)兼容的Task ,即它应该按照指定的方式运行: – 锁定的替代方法在某些情况下,您可能希望避免Lazy对象的默认锁定行为的开销。 在极少数情况下,可能存在死锁的可能性。 在这种情况下,您可以使用Lazy(LazyThreadSafetyMode)或Lazy(Func,LazyThreadSafetyMode)构造函数,并指定LazyThreadSafetyMode.PublicationOnly。 如果线程同时调用Value属性,这使Lazy对象能够在多个线程中的每个线程上创建一个延迟初始化对象的副本。 Lazy对象确保所有线程使用延迟初始化对象的相同实例并丢弃未使用的实例。 因此,降低锁定开销的成本是您的程序有时可能会创建并丢弃昂贵对象的额外副本。 […]