- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
因此,在一些帮助下,我更加清楚嵌套 GCD 在我的程序中是如何工作的。
原帖在:
Making sure I'm explaining nested GCD correctly
但是,您不需要阅读原始帖子,但基本上这里的代码在后台运行数据库执行并且 UI 是响应式的:
-(void)viewDidLoad {
dispatch_queue_t concurrencyQueue = dispatch_queue_create("com.epam.halo.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t serialQueue = dispatch_queue_create("com.epam.halo.queue2", DISPATCH_QUEUE_SERIAL);
for ( int i = 0; i < 10; i++) {
dispatch_async(concurrencyQueue, ^() {
NSLog(@"START insertion method%d <--", i);
dispatch_sync(serialQueue, ^() {
//this is to simulate writing to database
NSLog(@"----------START %d---------", i);
[NSThread sleepForTimeInterval:1.0f];
NSLog(@"--------FINISHED %d--------", i);
});
NSLog(@"END insertion method%d <--", i);
});
}
}
但是,当我开始重构它们并将它们放入方法中并使一切看起来不错时,UI 不再响应:
//一些数据库单例类
//串行队列在类的私有(private)扩展中声明。并在 init() 中创建
-(void)executeDatabaseStuff:(int)i {
dispatch_sync(serialQueue, ^() {
//this is to simulate writing to database
NSLog(@"----------START--------- %d", i);
[NSThread sleepForTimeInterval:1.0f];
NSLog(@"--------FINISHED-------- %d", i);
});
}
-(void)testInsert:(int)i {
dispatch_async(concurrencyQueue, ^() {
[self executeDatabaseStuff:i];
});
}
//ViewController.m
- (void)viewDidLoad {
//UI is unresponsive :(
for ( int i = 0; i < totalNumberOfPortfolios; i++) {
NSLog(@"START insertion method%d <--", i);
[[DatabaseFunctions sharedDatabaseFunctions] testInsert: i];
NSLog(@"END insertion method%d <--", i);
}
}
使重构版本工作的唯一方法是当我放置 dispatch_async(dispatch_get_main_queue():
for ( int i = 0; i < totalNumberOfPortfolios; i++) {
dispatch_async(dispatch_get_main_queue(), ^() {
NSLog(@"START insertion method%d <--", i);
[[DatabaseFunctions sharedDatabaseFunctions] testInsert: i];
NSLog(@"END insertion method%d <--", i);
});
}
所以我的问题是,我认为我使用 dispatch_async concurrencyQueue 将确保我的主线程不会被 dispatch_sync serialQueue 组合触及。为什么当我将它包装在一个对象/方法中时,我必须使用 dispatch_async(dispatch_get_main_queue()...) ?
似乎我的主线程是否在并发队列上执行 dispatch_async在 viewDidLoad 中,或在方法中,确实很重要。
我认为主线程正在将所有这些 testInsert 方法推送到其线程堆栈中。然后这些方法必须由主线程处理。因此,即使 dispatch_sync 没有阻塞主线程,主线程运行到 viewDidLoad 的末尾,并且必须等待所有 testInsert 方法被处理和完成才能移动到 Main Queue 中的下一个任务?
注意事项
所以我回到家再次测试:
for ( int i = 0; i < 80; i++) {
NSLog(@"main thread %d <-- ", i);
dispatch_async(concurrencyQueue, ^() {
[NSThread isMainThread] ? NSLog(@"its the main thread") : NSLog(@"not main thread");
NSLog(@"concurrent Q thread %i <--", i);
dispatch_sync(serialQueue, ^() {
//this is to simulate writing to database
NSLog(@"serial Q thread ----------START %d---------", i);
[NSThread sleepForTimeInterval:1.0f];
NSLog(@"serial Q thread --------FINISHED %d--------", i);
});
NSLog(@"concurrent Q thread %i -->", i);
});
NSLog(@"main thread %d --> ", i);
} //for loop
当我从 1 - 63 运行循环时,UI 没有被阻塞。我在后台看到我的数据库操作处理。
然后当循环为 64 时,UI 被阻塞 1 个数据库操作,然后返回正常。
当我使用 65 时,UI 会卡住 2 个数据库操作,然后返回正常...
当我使用 80 之类的东西时,它会从 64-80 被阻止...所以我等待 16 秒,然后我的 UI 才会响应。
当时我想不通为什么是64。所以现在我知道它的同时允许64个并发线程。 ...并且与将其包装在对象/方法中无关。 :D
非常感谢贡献者的大力帮助!
最佳答案
发生的事情是你向你的并发队列提交超过 64 个 block ,每个 block 都被 [NSThread sleepForTimeInterval:1.0f]
阻塞,迫使一个新的为每个操作创建线程。 因此,一旦达到线程限制,它就会备份并开始阻塞主线程。
我已经用 100 个“数据库写入”操作(在设备上)对此进行了测试,并且主线程似乎被阻塞,直到发生了 36 个操作(现在只剩下 64 个操作,因此主线程现在未-被阻止)。
使用单例不会给您带来任何问题,因为您是同步调用方法的,因此不应该有线程冲突。
最简单的解决方案就是为您的“数据库写入”操作使用单个后台串行队列。这样一来,只会创建一个线程来处理操作。
- (void)viewDidLoad {
[super viewDidLoad];
static dispatch_once_t t;
dispatch_once(&t, ^{
serialQueue = dispatch_queue_create("com.epam.halo.queue2", DISPATCH_QUEUE_SERIAL);
});
for (int i = 0; i < 100; i++) {
[self testInsert:i];
}
}
-(void)executeDatabaseStuff:(int)i {
//this is to simulate writing to database
NSLog(@"----------START--------- %d", i);
[NSThread sleepForTimeInterval:1.0f];
NSLog(@"--------FINISHED-------- %d", i);
}
-(void)testInsert:(int)i {
NSLog(@"Start insert.... %d", i);
dispatch_async(serialQueue, ^() {
[self executeDatabaseStuff:i];
});
NSLog(@"End insert... %d", i);
}
我不知道为什么在你的 for 循环中插入 dispatch_async(dispatch_get_main_queue(), ^() {}
对你有用......我只能假设它正在卸载“数据库写入”,直到界面加载完成。
关于ios - 主线程在 viewDidLoad 中的并发队列上执行 dispatch_async,或者在方法内执行事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34849078/
我正在学习 objective-c 教程,并注意到 viewDidLoad 中的代码放在 super viewDidLoad 下,而不是第一次调用 viewDidLoad。 代码放在viewDidLo
在Apple的scrollView示例中,他们没有这样称呼。我一直认为这是必须的。我为什么要这样调用它? 最佳答案 如果您要重写该方法,您仍然应该在 super 中调用该方法。即使父类(super c
这个问题已经有答案了: Why/when do we have to call super.ViewDidLoad? (6 个回答) 已关闭 4 年前。 override func viewDidLo
大家好,我有一个双 View Controller 。 我的 firstviewcontroller 有一个按钮,这个按钮发送 NSNotification,secontviewController
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Do I always have to call [super viewDidLoad] in the -v
我有一个关于子类化的问题。 我从我的第一个 View 开始:在我的 .h 文件中: @interface viewAController : UIViewController 在我的 .m 文件中:
我读到一篇文章说,当创建 UIViewController 类时,属性需要为零,然后 Storyboard 或在调用 viewDidLoad 时将其添加到值中。 它表示在构造对象时也无法初始化属性。
这是我当前的代码。我什至没有通过 viewDidLoad 方法覆盖,因为在它说 super viewdidload 的那一行它抛出错误 @interface for uitableview 为选择器
import UIKit class SecondViewController: UIViewController { @IBOutlet weak var labelA: UILabel!
我需要设置和存储一些可用于 View 的 NSUserDefaults 数据。这不适用于 viewDidLoad。 这可以做到吗? 在 viewDidLoad 之前我可以使用什么方法? 你会推荐什么?
当我向主视图 Controller 中的 viewDidLoad 添加方法时,我的 iPhone 应用程序崩溃了: #import "dbQuestionGetterViewController.h"
当用户切换到另一个程序然后再次返回时,原始程序的 View 将被另一个程序的新 View 替换。那么当用户切换回原来的程序时,viewDidLoad会被第二次调用吗? 我问这个是因为如果是这种情况,那
全部, 我正在从我的 applicationDidFinishLaunching 方法创建一个 windowController ... (void)applicationDidFinishLaunc
这个问题已经有答案了: Looking to understand the iOS UIViewController lifecycle (11 个回答) iPhone SDK: what is th
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 5年前关闭。 Improve this
我知道viewDidLoad在 UIViewController 期间可能会多次调用方法的生命周期。但这怎么可能?如何让它多次调用而不是直接调用它?我试过这样做: UIView *view = [
我在使用 iOS 时遇到了一点问题。我使用协议(protocol)在两个 View Controller 之间来回传递数据并手动切换 View 。我的问题是,当我关闭顶 View 时,不再调用底 Vi
我正在开发一款新应用程序,该应用程序主要用于组织网络内容中的信息。它将是一款用于监控道琼斯指数股息 yield 的金融应用程序。为此,需要执行几个步骤,但我现在正在执行第一步。我想选取道琼斯指数中的
我需要采用 viewDidLoad 方法中填充的变量来显示在连接到自定义单元格的标签上。我想做的是: 查找数据库中存储的用户盒子中的 SKU 使用SKU查找数据库中存储的产品详细信息 将产品详细信息存
我正在 viewDidLoad 中使用异步任务函数,根据返回的响应,我正在更改 View (颜色、文本...),但我有“错误”: 有时,当我更改 View 并返回 View 时,我的 View 背景没
我是一名优秀的程序员,十分优秀!