4

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

解压缩后的块将在解压缩后立即被主线程使用。

目前我这样做:

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 个,等等。
4

2 回答 2

1

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

也许您需要为任务设置到期日期,以免它们排队太多。听起来您需要低延迟处理。每个任务可以检查它的第一个动作是否超过 N 秒前被安排,如果是则立即退出。

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

于 2016-01-25T14:01:50.597 回答
0

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

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

Parallel.ForEach(compressedChunkData, chunkPair => {
    var compressedBytes = Convert.FromBase64String(chunkPair.Value);
    var chunk = Decompress(compressedBytes);
    TaskFinishActions.Enqueue(() => {
        chunk.PostSerialize();
        document.Chunks.Add(chunkPair.Key, chunk);
    });
});

如果您担心循环后代码变慢,请查看Jon Skeet 的这个答案。从本质上讲,您应该使用asyncandawait来处理或启动Parallel.Foreach单独的任务。

编辑:

让我们先弄清楚这一点:在像 windows 这样的操作系统上,没有为线程或进程保留 CPU 之类的东西。它适用于时间切片调度)。因此,即使您的解压缩线程可能不会阻塞您的主线程,它仍可能由于其他进程上的 CPU 密集型活动而被阻塞。将我们的偏好传达给操作系统的方法是使用优先级和 CPU 关联性。

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

  1. 也许你应该有一个单独的解压进程,并使用进程优先级和 CPU 亲和性来告诉操作系统它想在哪些内核上工作。
  2. 您可以创建一个管理 RequestQueue ( Producer-Consumer ) 的调度程序类。每个解压缩请求都应在单个线程上进行管理(将分配给单个逻辑 CPU)。确保您的调度程序使用不超过 (TOTAL_CPUS-1) (保持一个可用于主线程)
于 2016-01-25T00:12:12.237 回答