C# 如何确保Task.Factory.StartNew不会';你不能放慢主线的速度吗?
有一堆压缩数据块必须异步压缩-,而不以任何形式阻塞或减慢主线程 解压后的块将在解压后立即被主线程使用 目前我是这样做的:C# 如何确保Task.Factory.StartNew不会';你不能放慢主线的速度吗?,c#,concurrency,task-parallel-library,taskfactory,C#,Concurrency,Task Parallel Library,Taskfactory,有一堆压缩数据块必须异步压缩-,而不以任何形式阻塞或减慢主线程 解压后的块将在解压后立即被主线程使用 目前我是这样做的: foreach (var chunkPair in compressedChunkData) { var task = Task.Factory.StartNew<Chunk>(() => { var compressedBytes = Convert.FromBase64Str
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!!!
<代码>foreach(压缩dchunkData中的var chunkPair)
{
var task=task.Factory.StartNew(()=>
{
var compressedBytes=Convert.FromBase64String(chunkPair.Value);
var chunk=解压缩(压缩字节);
返回块;
}).继续((完成任务)=>
{
var chunk=finishedTask.Result;
TaskFinishActions.Enqueue(()=>
{
chunk.PostSerialize();
document.Chunks.Add(chunkPair.Key,chunk);
});
});
}
//当我们到达这里的时候,20毫秒已经过去了!!!
问题是,这似乎劫持了主线程运行的核心,这破坏了性能
有没有办法让TaskFactory
仅在主线程被阻塞的短暂时间内,每个核心都有线程,并且上下文切换远离主线程
编辑:foreach循环并不是代码中唯一变慢的部分,只要有相当数量的解压缩任务在运行,主线程就会显著变慢
EDIT2:要解压缩的新数据始终到达,循环不仅运行一次:
- 假设有250个项目首先到达
compressedChunkData
- 下一帧你有10个项目,下一个12,下一个0,下一个2,等等
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
和wait
来完成此任务,或者在单独的任务上启动Parallel.Foreach
编辑:
首先让我们弄清楚:在像windows这样的操作系统上,没有为线程或进程保留CPU这样的事情。它在时间片调度上工作)。因此,即使解压线程可能不会阻塞主线程,它也可能由于其他进程上CPU密集型活动而被阻塞。将我们的偏好传达给操作系统的方法是使用优先级和CPU相关性
还有其他方法需要更多的手动控制,因此需要更多的工作
您可以使用自定义的
TaskScheduler
,将线程优先级设置为较低的值。Windows总是先安排优先级较高的线程
也许你需要为任务设定一个截止日期,这样他们就不会排得太多。听起来您需要低延迟处理。每个任务都可以检查其第一个操作是否在N秒前计划,如果是,则立即退出
另一种设计是生产者/消费者场景,低优先级线程承担工作。考虑到您的需求,我认为没有必要这样做,但这是一个更灵活的解决方案。创建数百个任务不是问题。每个任务只是内存中的一个小数据结构。任务!=线程。您可以为您的问题设置尽可能高的主线程优先级。您正在运行一个
forach
,该循环的20ms不是正常且明显的吗?foreach循环不是问题,它有260个项目。4核。Rene Vogt,TaskcreationOptions.LongRunning只会让情况变得更糟,因为这意味着创建的线程可能比需要的多。创建260个任务并不理想。如果需要并行性,我会使用单个任务或任务。运行(()=>Parallel.ForEach(…)
。Charles Mager,是的,这似乎工作得更好。Parallel.ForEach块。这是不能接受的。即使您将它放在Task.Run(()=>Parallel.ForEach(…)中,也只有在您有一组固定的压缩数据时,它才能解决问题。如果要解压缩的新数据总是一个接一个地到达,而您仍然需要为每个数据创建新任务,该怎么办?这种方法根本不起作用。我必须说,如果您只需要对压缩的Chunkdata进行一次检查,而不是每一帧/迭代,Task.Run(()=>Parallel.ForEach(…)的效果会更好。@jbeur您是否尝试过使用async/await。我将以另一种方式更新答案