gpt4 book ai didi

c# - 在实现生产者/消费者模式时使用 Task.Yield 克服 ThreadPool 饥饿

转载 作者:行者123 更新时间:2023-11-30 12:20:07 29 4
gpt4 key购买 nike

回答问题:Task.Yield - real usages?我建议使用 Task.Yield 允许池线程被其他任务重用。在这样的模式中:

  CancellationTokenSource cts;
void Start()
{
cts = new CancellationTokenSource();

// run async operation
var task = Task.Run(() => SomeWork(cts.Token), cts.Token);
// wait for completion
// after the completion handle the result/ cancellation/ errors
}

async Task<int> SomeWork(CancellationToken cancellationToken)
{
int result = 0;

bool loopAgain = true;
while (loopAgain)
{
// do something ... means a substantial work or a micro batch here - not processing a single byte

loopAgain = /* check for loop end && */ cancellationToken.IsCancellationRequested;
if (loopAgain) {
// reschedule the task to the threadpool and free this thread for other waiting tasks
await Task.Yield();
}
}
cancellationToken.ThrowIfCancellationRequested();
return result;
}

void Cancel()
{
// request cancelation
cts.Cancel();
}

但是一位用户写道

I don't think using Task.Yield to overcome ThreadPool starvation while implementing producer/consumer pattern is a good idea. I suggest you ask a separate question if you want to go into details as to why.

有人知道,为什么这不是个好主意?

最佳答案

您的问题的评论中有一些要点。作为您引用的用户,我只想总结一下:使用正确的工具来完成工作。

使用 ThreadPool 感觉不是执行多个连续的 CPU 绑定(bind)任务的正确工具,即使您尝试通过将它们变成状态机来组织一些协作执行,从而为每个任务提供 CPU 时间其他使用 await Task.Yield()。线程切换相当昂贵;通过在紧密循环中执行 await Task.Yield(),您会增加大量开销。此外,您永远不应该接管整个 ThreadPool,因为 .NET 框架(和底层操作系统进程)可能需要它来做其他事情。在相关说明中,TPL 甚至具有 TaskCreationOptions.LongRunning 选项,该选项请求不在 ThreadPool 线程上运行任务(相反,它使用 创建一个普通线程new Thread() 在幕后)。

也就是说,在一些专用的池外线程上使用具有有限并行性的自定义 TaskScheduler 可能会是一个不同的东西。至少,await continuations 会发布在同一个线程上,这应该有助于减少切换开销。这让我想起了我前一段时间试图用 ThreadAffinityTaskScheduler 解决的另一个问题。 .

不过,根据特定情况,通常最好使用现有的行之有效且经过测试的工具。仅举几例:Parallel Class , TPL Dataflow , System.Threading.Channels , Reactive Extensions .

还有一整套现有的工业级解决方案来处理发布-订阅模式(RabbitMQ、PubNub、Redis、Azure Service Bus、Firebase Cloud Messaging (FCM)、Amazon Simple Queue Service (SQS) 等)。

关于c# - 在实现生产者/消费者模式时使用 Task.Yield 克服 ThreadPool 饥饿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53263258/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com