首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确保Task.Factory.StartNew不会减慢主线程的速度?

如何确保Task.Factory.StartNew不会减慢主线程的速度?
EN

Stack Overflow用户
提问于 2016-01-24 18:39:18
回答 2查看 1.3K关注 0票数 4

有一堆压缩的数据块必须被异步地压缩--,而不阻塞或减慢主线程的任何形状或形式。

解压缩块一旦解压缩,主线程就会使用它们。

目前我这样做:

代码语言:javascript
复制
foreach (var chunkPair in compressedChunkData)
{                        
    var task = Task.Factory.StartNew<Chunk>(() =>
    {
        var compressedBytes = Convert.FromBase64String(chunkPair.Value);
        var chunk = Decompress(compressedBytes);
        return chunk;
    }).ContinueWith((finishedTask) =>
    {
        var chunk = finishedTask.Result;
        TaskFinishActions.Enqueue(() =>
        {
            chunk.PostSerialize();
            document.Chunks.Add(chunkPair.Key, chunk);
        });
    });
}
// By the time we get here 20ms has passed!!!

问题是,这似乎劫持了主线程正在运行的核心,这破坏了性能。

是否有一种方法可以使TaskFactory在每个内核上都有线程,而上下文只在主线程被阻塞的那些短暂时刻才从主线程中切换?

编辑:foreach循环并不是代码中唯一缓慢的部分,只要有相当数量的解压缩任务正在运行,主线程就会显著减慢。

EDIT2:用于解压缩的新数据始终到达,循环不只是运行一次:

  • 假设您有250个项目首先到达compressedChunkData
  • 下一帧你有10个项目,下一个12,下一个0,下一个2,等等。
EN

回答 2

Stack Overflow用户

发布于 2016-01-25 14:01:50

您可以使用自定义TaskScheduler将线程优先级设置为低值。Windows总是首先安排更高优先级的线程。

也许您需要在任务上设置一个过期日期,这样它们就不会排太多队。听起来你需要低延迟处理。每个任务都可以检查它的第一个动作是否在N秒钟前就计划好了,如果是,可以立即退出。

另一种设计是生产者/消费者方案,低优先级线程承担工作。考虑到您的需求,我认为没有必要这样做,但这是一个更灵活的解决方案。创建数百个任务不是问题。每个任务只是一个小内存数据结构.任务!=线程。

票数 1
EN

Stack Overflow用户

发布于 2016-01-25 00:12:12

您是否担心for循环减慢或循环后面的代码运行缓慢?

如果您担心for循环,那么有一个简单的解决方案,在任何情况下都应该遵循。您可以提供一个ParallelOptions类实例来控制并发的程度。

代码语言:javascript
复制
Parallel.ForEach(compressedChunkData, chunkPair => {
    var compressedBytes = Convert.FromBase64String(chunkPair.Value);
    var chunk = Decompress(compressedBytes);
    TaskFinishActions.Enqueue(() => {
        chunk.PostSerialize();
        document.Chunks.Add(chunkPair.Key, chunk);
    });
});

如果您担心循环结束后会放慢代码的速度,那么请看这是乔恩·斯基特的回答。本质上,您应该使用asyncawait来完成这个任务,或者在单独的任务上启动Parallel.Foreach

编辑:

让我们先弄清楚这一点:在像windows这样的操作系统上,不存在为线程或进程预留CPU的事情。它适用于时间切片调度)。因此,即使您的解压缩线程可能不会阻止您的主线程,它也可能由于其他进程上的CPU密集活动而被阻塞。将我们的偏好传递给操作系统的方法是使用优先级和CPU亲和力。

还有其他方法需要更多的人工控制,因此需要更多的工作。

  1. 也许您应该有一个单独的解压缩进程,并使用进程优先级和CPU亲和力来告诉操作系统它想要处理的核心。
  2. 您可以创建一个管理RequestQueue (生产者-消费者 )的调度程序类。每个解压缩请求应该在一个线程上管理(该线程将被分配给一个逻辑CPU)。确保您的调度程序使用的不超过(TOTAL_CPUS 1)(保持主线程可用)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34979824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档