gpt4 book ai didi

ios - 如何在不达到全局GCD限制的情况下并行处理许多(100+)个任务?

转载 作者:行者123 更新时间:2023-12-01 17:29:53 24 4
gpt4 key购买 nike

问题:

当在后台延迟加载100个以上的图标列表时,我达到了GCD线程限制(64个线程),这导致我的应用在主线程上冻结并带有semaphore_wait_trap。我想重组我的线程代码以防止这种情况的发生,同时仍然异步加载图标以防止UI阻塞。

上下文:

我的应用程序在屏幕上加载了SVG图标。金额平均在10-200之间。通过使用本地SVG图像或远程SVG图像(如果具有自定义图标)绘制图标,然后对其进行后处理以获得最终图像结果。

因为这要花一些时间,并且它们对于用户而言并不重要,所以我想在后台加载它们并对其进行后处理,以便它们随着时间的流逝而弹出。对于每个图标,我使用以下内容:

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
//code to be executed in the background
SVGKImage *iconImage = [Settings getIconImage:location];
dispatch_async(dispatch_get_main_queue(), ^{
//code to be executed on the main thread when background task is finished
if (iconImage) {
[iconImgView setImage:iconImage.UIImage];
}
});
});
getIconImage方法处理基本SVG的初始加载,基本SVG会与 [NSInputStream inputStreamWithFileAtPath:path](如果是本地)同步,并与 [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&errorWithNSData](如果应远程加载)同步读取。这一切都是同步发生的。

然后,在返回SVG并将其放入主线程中的 UIImageView之前,需要对SVG进行重新着色的一些后期处理。

问题:

有没有一种方法可以构造我的代码以允许并行后台加载但防止由于线程过多而导致的死锁?

解决方案编辑:
_iconOperationQueue = [[NSOperationQueue alloc]init];
_iconOperationQueue.maxConcurrentOperationCount = 8;

// Code will be executed on the background
[_iconOperationQueue addOperationWithBlock:^{
// I/O code
SVGKImage *baseIcon = [Settings getIconBaseSVG:location];

// CPU-only code
SVGKImage *iconImage = [Settings getIconImage:location withBaseSVG:baseIcon];
UIImage *svgImage = iconImage.UIImage; // Converting SVGKImage to UIImage is expensive, so don't do this on the main thread
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Code to be executed on the main thread when background task is finished
if (svgImage) {
[iconImgView setImage:svgImage];
}
}];
}];

最佳答案

而不是直接将GCD与并发队列一起使用,请使用NSOperationQueue。将其maxConcurrentOperationCount设置为合理的值,例如4或8。

如果可以的话,还应该将I/O与纯计算分开。对I/O使用限制宽度的操作队列。可以使用无限制的操作队列或纯GCD进行纯计算。

原因是I/O块。 GCD检测到系统处于空闲状态,并启动另一个工作线程,并从队列中启动另一个任务。这也会阻塞I/O,因此它会做更多的工作,直到达到极限为止。然后,I/O开始完成,任务解除阻塞。现在您已超额预订了系统资源(即CPU),因为正在运行的任务多于核心,并且突然间它们实际上正在使用CPU而不是被I/O阻塞。

纯粹的计算任务不会引发此问题,因为GCD认为系统实际上很忙,在更早的任务完成之前不会使更多任务出队。

关于ios - 如何在不达到全局GCD限制的情况下并行处理许多(100+)个任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30933323/

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