何时应该在通道中使用AllowSynchronousContinuations选项?

7
我正在实现Asp.Net Core应用程序中的简单后台作业队列。我创建了BackgroundJobQueue,它在底层使用BoundedChannel<T>来排队项,这些项将通过HostedService进行处理。阅读文档时,我遇到了有关通道的ChannelOptions.AllowSynchronousContinuations设置。
根据msdn上面的说明:
将此选项设置为true可以通过避免调度其他工作项来提供可衡量的吞吐量改进。但是,这可能会以减少并行性的代价为代价,例如生产者可能是执行与消费者关联的工作的那个人,并且如果没有经过深思熟虑地完成,则可能导致意外的相互作用。默认值为false。
我不太明白在我的情况下将此选项设置为true是否是一个好选择。有人能解释一下,并提供此选项何时有用/无用/有害的示例吗?
编辑:
我得到的解释是:
根据官方声明,当生产者依赖于消费者时,它等待消费者的工作完成,然后开始自己的工作,如果启用该选项,则生产者经历更多的空闲时间。但是,如果禁用了该选项,由于并行性,生产者经历较低的空闲时间。
启用选项不好吗?因为API请求将需要更长时间来处理,因为生产者将保持空闲更长时间。让我解释一下我的意思。假设我想在控制器中排队后台作业。
public async Task<IActionResult> Action()
{
    // some code
   await _backgroundJobQueue(() => ....);
   return Ok();
}

如果启用了该选项,那么生产者将会有更多的空闲时间,因此它执行操作所需的时间会更长。

如果可以的话,请提供实验结果以进行确认。当所有工作完成时,您可以设置定时器。 - A Farmanbar
我建议不要使用它,除非性能分析表明它会有用。 "意外的交互" [可能包括死锁] (https://blog.stephencleary.com/2012/12/dont-block-in-asynchronous-code.html)。 - Stephen Cleary
@StephenCleary 一个好观点 - Neistow
2个回答

2
如果队列不为空,则所有操作都是异步的。
如果队列为空,则AllowSynchronousContinuations开始发挥作用。
以下是非常简单的近似样例:
AllowSynchronousContinuations为TRUE。
void Producer()
{
    T instance = new T(); 
    
    Consumer(instance);

    // 'instance' object passed directly to the consumer and the producer will get execution control once the consumer completes processing.
}

AllowSynchronousContinuations为FALSE

void Producer()
{
    T instance = new T(); 
    
    Task.Run(() => Consumer(instance));

    // instance stored in queue and work scheduled for execution. The producer will get execution control immediately after scheduling
}

еҰӮжһңеҸҜд»Ҙзҡ„иҜқпјҢиҜ·жҸҗдҫӣжӣҙеӨҡе…ідәҺSystem.Threading.Channels.Channelзҡ„е…·дҪ“з»ҶиҠӮгҖӮиҝҷйҮҢзҡ„Consumerж–№жі•жҳҜд»Җд№ҲпјҹиҖҢдё”йҖҡйҒ“еҜ№иұЎеңЁе“ӘйҮҢпјҹ - Eugene

1
您有一个后台队列。因此,您正在使用排队作业同步操作。最好启用它,因为您不希望并行处理,而文档声称“它提供了可衡量的吞吐量改进”。

例如,生产者可能是执行与消费者相关联工作的人

根据官方声明,当生产者依赖于消费者时,它会等待消费者的作业完成,然后开始其工作,如果您启用该选项,则生产者会经历更多的空闲时间。但是,如果您禁用该选项,由于并行处理,生产者的空闲时间较少。
这就是我理解和举例说明的内容。

@Neistow 如果生产者依赖于消费者,否则它就不会受到影响。 - A Farmanbar
那么它会像“点火并忘记”一样工作吗?就我所了解的,生产者不依赖于消费者。 - Neistow
@Neistow 根据你的逻辑,是的,启用它会更好,因为并行在这里并不更有效。 - A Farmanbar
这不完全是一个问题的范围,但当有界通道已满时会发生什么情况呢?代码将异步等待,直到有足够的空间来排队作业?因此,理论上,如果我的通道已满,我的api将无法处理请求? - Neistow
@Neistow 理论上,如果你遇到这样的流量,在启用并行处理时会更容易崩溃,因为它的成本更高。 - A Farmanbar

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