需要一些关于dispatch_queue_create和RunLoop的澄清。他们之间共享 RunLoop

问题描述 投票:0回答:1

我正在使用 Objective-C 开发 iOS 框架。

我使用

dispatch_queue_t
创建了一个
dispatch_queue_create
。并调用
CFRunLoopRun()
来运行队列中的 runloop。

但是,看起来dispatch_queue_t共享了RunLoop。有些类添加了无效的计时器,当我调用

CFRunLoopRun()
时,它在我这边崩溃了。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.queue1 = dispatch_queue_create("com.queue1", DISPATCH_QUEUE_CONCURRENT);
    self.queue2 = dispatch_queue_create("org.queue2", DISPATCH_QUEUE_CONCURRENT);
}

- (IBAction)btnButtonAction:(id)sender {
    
    dispatch_async(self.queue1, ^{
        
        NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
        runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
        NSLog(@"Queue1 %p run: %@", self.queue1, runloop);
        
        //NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1 target:self selector:@selector(wrongSeletor:) userInfo:nil repeats:NO];
        //[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    });
    
    dispatch_async(self.queue2, ^{
        NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
        runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
        NSLog(@"Queue2 %p run: %@", self.queue2, runloop);
        
        CFRunLoopRun();
    });
}

有时他们采用相同的 RunLoop:

https://i.stack.imgur.com/wGcv3.png

======

您可以通过取消注释

NSTimer
的代码来看到崩溃。
queue1
中已经添加了NSTimer,但是在
CFRunLoopRun()
中调用
queue2
时它仍在运行。

我读过一些描述,例如:需要一些关于调度队列、线程和 NSRunLoop 的说明

他们这么说:

system creates a run loop for the thread
。但是,在我的检查中,他们正在共享 RunLoop。

这对我来说很伤心,因为我在生产中调用

CFRunLoopRun()
时会发生崩溃。

objective-c grand-central-dispatch nsrunloop runloop cfrunloop
1个回答
0
投票

如果你想在调度队列上运行某些东西,我们通常不会使用

NSTimer
。相反,我们将使用调度计时器。这根本不需要运行循环。

NSTimer
不同,我们需要保留对计时器的强引用:

@property (nonatomic, strong) dispatch_source_t timer;

然后,启动计时器:

- (void)startTimer {
    dispatch_queue_t queue = dispatch_queue_create("com.domain.app.timer", DISPATCH_QUEUE_SERIAL);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(self.timer, ^{
        // this is called when the timer fires
    });
    dispatch_resume(self.timer);
}

要停止计时器,只需松开它即可:

- (void)stopTimer {
    self.timer = nil;
}
© www.soinside.com 2019 - 2024. All rights reserved.