【问题标题】:Dispach queue and semaphore调度队列和信号量
【发布时间】:2014-04-26 15:06:19
【问题描述】:

我不确定我这样做是否正确 - 我想在我的应用程序后台异步运行远程 URL 请求。用户不必等待。但是,由于在后台运行,他可能会触发多个请求。我没有信号量和并发产生异常。因此,我相信我必须通过信号量来保护请求。当请求完成时,我对 MKMapView 注释运行更新。 我的意思是在后台同步运行请求。

我有下面的代码,但是,即使使用当前的信号量实现,它也会失败。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        dispatch_semaphore_t requestSemaphore = dispatch_semaphore_create(1);
        dispatch_semaphore_wait(requestSemaphore, DISPATCH_TIME_FOREVER);

        MapAnnotation* theAnnotation = (MapAnnotation*)button.property;

        [theAnnotation.data update]; //this must be protected

        [self.mapView removeAnnotation:theAnnotation];
        MapAnnotation* newAnnotation = [theAnnotation.data getMapAnnotation];
        [self.mapView addAnnotation:newAnnotation];
        [self.mapView selectAnnotation:newAnnotation animated:YES];

        dispatch_semaphore_signal(requestSemaphore);
    });

当我运行多个请求时,dispatch_async 出现此错误 - 但它在顺序模式下工作

*** Terminating app due to uncaught exception 'NSRangeException', 
reason: 'Cannot remove an observer <MKPopoverBasedAnnotationCalloutController 0x10c86bd50> 
for the key path "annotation.title" from <MKPinAnnotationView 0x11798f490> 
because it is not registered as an observer.'

谢谢!

【问题讨论】:

  • 您的意思是要在发出新请求之前取消任何正在进行的请求?
  • 我的意思是在后台同步运行请求。基本上就像一个队列。

标签: ios objective-c mkmapview grand-central-dispatch semaphore


【解决方案1】:

不要使用 GCD,使用 NSOperationQueue 和操作(为简单起见,可以是块操作)。然后您可以使用setMaxConcurrentOperationCount: 来确保在任何时候都只处理一个操作(请求)。

还请注意,您必须在更新 UI(地图视图)之前切换回主线程,否则您会遇到异常(这可能是您当前看到的异常的原因)。

【讨论】:

  • 切换回主线程是错误的原因。也会使用队列。谢谢!
【解决方案2】:

不确定为什么您认为需要信号量,只需使用串行队列即可。以下方法有什么问题?

  dispatch_queue_t serialQueue = dispatch_queue_create("serial_queue", DISPATCH_QUEUE_SERIAL);
  dispatch_async(dispatch_get_global_queue(serialQueue, 0), ^{

    // Your URL request code


    // Once you finish downloading you update the UI
    dispatch_async(dispatch_get_main_queue(), ^{
        MapAnnotation *theAnnotation = (MapAnnotation*)button.property;

        [theAnnotation.data update]; //this must be protected

        [self.mapView removeAnnotation:theAnnotation];
        MapAnnotation* newAnnotation = [theAnnotation.data getMapAnnotation];
        [self.mapView addAnnotation:newAnnotation];
        [self.mapView selectAnnotation:newAnnotation animated:YES];
    };
});

【讨论】:

    猜你喜欢
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 2021-03-01
    • 2017-04-18
    相关资源
    最近更新 更多