vos*_*d01 10 .net c# garbage-collection task task-parallel-library
当使用API和从任务并行库派生的类时,开发人员何时需要关注垃圾收集的影响?
.NET Task实例在运行期间是否超出范围?,似乎给人一种安全感,你不必担心将任务保持在范围内.但问题似乎仅限于在ThreadPool上运行的任务,然后rooted由ThreadPool进行.但是,如果我正确理解这篇MSDN博客文章,那么SO问题的建议通常不适用,因为来自TaskCompletionSource的任务并不相似rooted.
是直接使用TaskCompletionSource的唯一关注时间吗?
但是,在使用API时,您不知道任务的来源.那么你是否需要担心存储对continuation的引用,以防提供Task来自一个TaskCompletionSource或其他一些非根源?
从需要考虑任务是否已植根(是否同步的异步I/O任务?),这似乎很快变得不方便和复杂.我很难找到关于主题的信息,但它是一个很受欢迎的库,我觉得我不应该阅读反编译的源代码来确定我是否需要担心垃圾收集器的竞争条件,所以我想我必须是遗失或误解的东西.
当你有未完成时TaskCompletionSource,总有两个选择:
有些事可能会在未来完成TCS.这意味着某些东西含有对TCS的引用,这意味着它无法获得GCed.
正常的规则仍然适用于那个东西,所以你可能需要担心保持这种根源.
什么都不会完成那个TCS.这意味着TCS及其任务很快就会得到GC,但没有工作没有风险(因为没有工作).
唯一值得关注的是当Task由一个TaskCompletionSource和任何应该利用TaskCompletionSource来设置结果的人提供垃圾收集时.不幸的是,在这种情况下,API的消费者无法做任何事情,除非他们可以访问并且可以保存对任何内容的引用.因此,对于API实现者的提供者而言,这也是在返回这样的任务时需要意识到这一点的问题.
由于缺乏更好的资源,我不得不通过组合测试(试错)和阅读源代码来确定上述内容.但是,在没有文档的情况下,这些可能是实现细节,并且可能会在.NET Framework的未来版本中进行更改.
本Task类是密封的,看来,TaskCompletionSource通过使用非公开API的工作.因此,排除可能使用非公共API的其他MS API并假设库不是反射性地使用Task内部组件,唯一关注的实现是Task和TaskCompletionSource.
除了那些创建者TaskCompletionSource,Task使用Task或上的成员创建TaskFactory.任何由这些方法中的任何一个创建的开始 Task都绑定到a TaskScheduler.由于根据基于任务的异步模式指南(摘录)应该启动任何返回,因此非启动不是消费者需要担心的情况.
根据TaskScheduler.QueueTask关于MSDN(强调我的)的文档:
典型的实现将任务存储在内部数据结构中,该内部数据结构将由将在未来某个时间执行这些任务的线程提供服务.
因此,只要所使用的TaskScheduler实现遵循该规则,调度程序就会使得对该任务保持引用.只要调度程序使用的数据结构处于活动状态,这应该使Task保持活动状态.
TaskScheduler构建到框架中的两个实现在排队任务的存储方面应该是安全的.一个是单例,另一个是后备,SynchronizationContext因此只要上下文存在,排队的任务就会生根.
用于TaskScheduler在活动实现的静态列表中注册所有创建的实例TaskScheduler实例的基础构造函数,这可以防止任何自定义实现在其他情况下可能有资格进行收集时进行垃圾回收.TaskScheduler除非TaskScheduler在排队任务中做一些粗鲁的事情,否则不会出现与自定义范围相关的问题.
总的来说,这里没有什么可担心的.
TaskCompletionSources不保证可以被任何东西植根.[1]因此,在设置结果之前,TaskCompletionSource确实存在垃圾收集的可能性.
如果用于确保完成TaskCompletionSource的相关对象是对象的成员,则维护对调用Task-returning方法的对象的引用可能会有所不同.虽然我找不到TAP/TPL的任何指导原则,但应该避免这种情况,我希望它们在发生时能够清楚地记录下来.
TaskCompletionSource返回的Task不维护对原始TaskCompletionSource的引用,更不用说引用TaskCompletionSource来设置结果的其他内容了.因此,使用者是否维护对返回的Task的引用不会影响此问题.
在完成所需的对象仅限于任务返回方法的情况下,API使用者实际上无法确保正确性,并且这种情况应被视为提供API中的错误.