等待在串行调度队列上执行的代码块

时间:2013-01-03 15:45:10

标签: objective-c thread-safety grand-central-dispatch

所以我有一个函数来准备代码块并安排它在串行调度队列上同步运行。我知道这个串行队列将在一个新线程上运行。然而,问题是代码块修改了一个它传回给函数的变量,而该函数反过来又要将它作为返回值返回。以下代码将有助于澄清情况:

-(DCILocation*) getLocationsByIdentifier: (NSString*) identifier andQualifier: (NSString*) qualifier {

    __block DCILocation* retval = nil;

    NSString* queryStr = [self baseQueryWithFilterSet:nil];
    queryStr = [queryStr stringByAppendingString:@" (identifier = ? OR icao = ?) AND qualifier = ?"];

   [self.queue inDatabase:^(FMDatabase *db) {
        FMResultSet* results = [db executeQuery:queryStr,
                               [identifier uppercaseString],
                               [identifier uppercaseString],
                               [qualifier uppercaseString]];
        if ((nil != results) && [results next]) {
             dispatch_async(dispatch_get_main_queue(), ^{
                 retval = [DCIAirportEnumerator newAirportForStatement:results];
             });
            [results close];
        }
   }];

   return retval;
}

“self.queue”是块将在其上运行的串行调度队列。请注意,该块修改“retval”并通过将dispatch_async调用嵌套到主线程来更新它。然而,担心的是,在串行调度队列上运行的代码块能够修改它之前,可能会调用“return retval”(函数的最后一行)。这将导致返回“nil”。

关于如何确保函数在返回之前不会返回由于在串行队列上执行的块所修改的任何想法?

2 个答案:

答案 0 :(得分:4)

  

关于如何确保该功能没有的任何想法   返回直到由在块上执行的块修改的retval   串行队列?

如果您需要等待结果,那么您的代码仍然是同步的,您也可以在您的方法中而不是在串行队列中运行它。所以这是第一个选择:不要在这里使用块。

第二个选项是重构代码,使其真正异步运行。找到依赖于返回值retval的代码,并将其分解为单独的方法或块。然后设置阻止retval调用retval时调用的块。

答案 1 :(得分:-2)

阻止后,您可以添加

while(YES) {
    if(variable) {
        break;
    }
}

然后在定义retval

之后在dispatch_async中添加
variable = YES;

您只需要在阻止之前定义 __block BOOL variable = NO;