异步操作在未被处理时等待在哪里?

5
如果我在C#中启动一组异步操作(任务),每个任务都会从网络上下载一些内容,然后我使用Task.WhenAny()处理第一个可用的任务结果,那么当主线程处理结果时,其他异步操作在哪里“等待”? 我只能假设,在操作系统级别上有某种内部队列存储状态以及在后台发生的下载结果。我的问题是,这个队列位于何处,是否存在这个队列溢出尚未处理的异步操作结果的任何危险?

我想象任务队列在“CLR级别”上。 - user2864740
我也有同样的想法,但我想确定一下 :) - Razor
你是否关注过由WaitAny()未处理的异步操作抛出的异常? - qxg
1个回答

7

TPL任务计划程序 跟踪通过 Task.Run, Task.Factory.StartNew, Task.ContinueWith, Task.RunTask.RunSynchronously 启动的任务。

对于 Promise 风格的任务(使用 TaskCompletionSource 创建的任务),引用由 I/O 完成回调或事件处理程序保留。Stephen Cleary 有一篇与此类任务相关的 优秀博客文章

对于编译器生成的状态机任务(由带有await语句的async方法返回),只要任何“内部”任务(或自定义等待)仍在“进行中”,该任务就会保持活动状态。在这种情况下,继续回调由任务awaiter(例如TaskAwaiter)保存。这个编译器生成的回调会对环境(“外部”)任务产生强间接引用。当“内部”任务完成时,回调将通过SynchronizationContext.PostTaskScheduler.Current任务计划程序(如果在await点未捕获同步上下文)进行调度。
在使用自定义awaiter的情况下,可能需要强制保持await继续传递给INotifyCompletion.OnCompleted的回调,以防止环境任务在“进行中”时被垃圾回收。
我的问题是,这个队列在哪里,是否存在这个队列溢出的危险,因为尚未处理异步操作的结果会被存储在此队列中?如果任务排队的速度比完成的速度快,长期来看可能会耗尽内存。这是排队理论所涉及的常见问题,不是TPL任务特有的问题。

我确定,对于ContinueWith,继续操作会作为“前置”任务的一部分被保留下来,不是吗? - Shmil The Cat
@ShmilTheCat 我的意思是ContinueWith返回的Task实例本身。 - noseratio - open to work

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接