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