【问题标题】:Where do asynchronous operations wait when they are not being dealt with?当异步操作没有被处理时,它们在哪里等待?
【发布时间】:2014-05-09 18:37:58
【问题描述】:

如果我在 C# (Tasks) 中启动一组异步操作,每个都从 Web 下载一些内容,然后我使用 Task.WhenAny() 处理第一个可用的 Task 结果,而其他异步操作在哪里“等待”主线程处理结果?

我只能假设在操作系统级别存在某种内部队列,用于存储状态以及在后台发生的下载结果。

我的问题是,这个队列在哪里,这个队列有没有被尚未处理的异步操作结果溢出的危险?

【问题讨论】:

  • (我想任务队列处于“CLR 级别”。)
  • 我也有同样的想法,但我很想知道 :)
  • 您是否担心未由 WaitAny() 处理的异步操作引发的异常?

标签: .net asynchronous task-parallel-library async-await


【解决方案1】:

TPL Task Schedulers 跟踪通过Task.RunTask.Factory.StartNewTask.ContinueWithTask.RunTask.RunSynchronously 启动的任务。

对于promise 风格的任务(使用TaskCompletionSource 创建的任务),引用由I/O 完成回调或事件处理程序保存。 Stephen Cleary 有一个与此类任务相关的great blog post

对于编译器生成的状态机任务(由 async 方法返回的带有 await 语句的任务),只要等待任何“内部”任务(或 custom awaiter),该任务就会保持活动状态是“飞行中”。在这种情况下,任务等待者(例如,TaskAwaiter)保留继续回调。这个编译器生成的回调持有对环境(“外部”)任务的强烈间接引用。当“内部”任务完成时,回调将通过SynchronizationContext.PostTaskScheduler.Current 任务调度程序调度(如果在await 处没有捕获同步上下文)。

如果使用自定义等待者,one may need 会强烈保留传递给INotifyCompletion.OnCompletedawait 延续回调,以防止环境任务在“进行中”时被垃圾收集。

我的问题是,这个队列在哪里,有什么危险吗? 这个队列溢出异步操作的结果 哪些还没有处理?

如果任务排队的速度比完成任务的速度快,从长远来看,您最终可能会耗尽内存。这是排队理论处理的一个常见问题,它不是特定于 TPL 任务的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 2022-01-02
    • 2021-11-01
    • 1970-01-01
    相关资源
    最近更新 更多