有一堆压缩的数据块必须被异步地压缩--,而不阻塞或减慢主线程的任何形状或形式。
解压缩块一旦解压缩,主线程就会使用它们。
目前我这样做:
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:用于解压缩的新数据始终到达,循环不只是运行一次:
compressedChunkData发布于 2016-01-25 14:01:50
您可以使用自定义TaskScheduler将线程优先级设置为低值。Windows总是首先安排更高优先级的线程。
也许您需要在任务上设置一个过期日期,这样它们就不会排太多队。听起来你需要低延迟处理。每个任务都可以检查它的第一个动作是否在N秒钟前就计划好了,如果是,可以立即退出。
另一种设计是生产者/消费者方案,低优先级线程承担工作。考虑到您的需求,我认为没有必要这样做,但这是一个更灵活的解决方案。创建数百个任务不是问题。每个任务只是一个小内存数据结构.任务!=线程。
发布于 2016-01-25 00:12:12
您是否担心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);
});
});如果您担心循环结束后会放慢代码的速度,那么请看这是乔恩·斯基特的回答。本质上,您应该使用async和await来完成这个任务,或者在单独的任务上启动Parallel.Foreach。
编辑:
让我们先弄清楚这一点:在像windows这样的操作系统上,不存在为线程或进程预留CPU的事情。它适用于时间切片调度)。因此,即使您的解压缩线程可能不会阻止您的主线程,它也可能由于其他进程上的CPU密集活动而被阻塞。将我们的偏好传递给操作系统的方法是使用优先级和CPU亲和力。
还有其他方法需要更多的人工控制,因此需要更多的工作。
https://stackoverflow.com/questions/34979824
复制相似问题