使用NSOperationQueue获取BAD_EXEC

时间:2016-04-11 14:33:12

标签: ios nsoperationqueue

我需要在我的应用中运行异步任务

我有以下代码:

- (NSDictionary *)parallelSendSync:(NSDictionary *)requests {

    NSMutableDictionary *responseDict = [[NSMutableDictionary alloc] init];
    for (NSString *key in [requests allKeys]) {
        [_parallelSendQueue addOperationWithBlock:^{
            NSDictionary *sendResult = [self send:requests[key] :nil];
           [responseDict setObject:sendResult forKey:key]; //this line sometimes throws BAD_EXEC
         }];

    }
     [_parallelSendQueue waitUntilAllOperationsAreFinished];

    return responseDict.copy;

}

_parallelSendQueue接受最多5个并发操作

不幸的是,这只是部分时间有效,有时它可以正常工作,有时会抛出BAD_EXEC

坏执行官可能是什么原因?

2 个答案:

答案 0 :(得分:2)

如果您有五个并行运行的任务尝试更改某些字典,则可能会发生崩溃。必须使用@synchronized更改responseDict。 NSMutableDictionary不是线程安全的。

答案 1 :(得分:2)

问题是多个线程正在使用相同的对象,这可能导致非线程安全对象的内存损坏。

您有两种选择:

  • 从多个线程或并行队列锁定您正在使用的对象,这样一次只能有一个操作可以更改它
  • 发送到拥有共享对象的一个​​特定线程或串行队列并从那里进行更改(但要注意,如果您调度到当前正在调用waitUntilAllOperationsAreFinished的同一线程,程序将被解锁)

我认为您的最佳解决方案是锁定:

- (NSDictionary *)parallelSendSync:(NSDictionary *)requests {

    NSMutableDictionary *responseDict = [[NSMutableDictionary alloc] init];
    for (NSString *key in [requests allKeys]) {
        [_parallelSendQueue addOperationWithBlock:^{
            NSDictionary *sendResult = [self send:requests[key] :nil];
            // synchronized locks the object so there is no memory corruption
            @synchronized(responseDict) {
              [responseDict setObject:sendResult forKey:key];
            }
         }];
    }
     [_parallelSendQueue waitUntilAllOperationsAreFinished];

    return responseDict.copy;

}