使用 NSOperationQueue 获取 BAD_EXEC

Getting BAD_EXEC using 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

执行错误的原因可能是什么?

如果您有五个并行任务 运行 试图更改 some 字典,则预计会发生崩溃。必须使用@synchronized 来更改 responseDict。 NSMutableDictionary 不是线程安全的。

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

你有两个选择:

  • 从多个线程或并行队列中锁定您正在使用的对象,这样一次只有一个操作可以更改它
  • 分派到拥有共享对象的一个​​特定线程或串行队列并从那里更改它(但要注意,如果您分派到当前正在调用的同一线程 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;

}