【问题标题】:Waiting for a block of code to execute on a serial dispatch queue等待一段代码在串行调度队列上执行
【发布时间】:2013-01-03 15:45:10
【问题描述】:

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

-(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”。

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

【问题讨论】:

  • self.queue 是什么?由于我们不知道您的队列实现,我们无法帮助您解决序列化问题。
  • 您需要异步解决方案来解决同步问题。问问自己,我真的需要调度异步,因为我必须等待它吗?

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


【解决方案1】:

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

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

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

【讨论】:

  • 感谢指导,很有道理。还有一个快速的问题。如果,假设在那个块中我调用一个方法,该方法是该块所在的同一个类的一部分,使用'[self someMethod...]',那会正常工作吗?我很担心,因为该块将在不同的线程上执行,因此无法访问外部方法。
  • 你可以这样做。详细答案见Objective C - Calling [self methodName] from inside a block?
【解决方案2】:

在你的块之后,你可以添加

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

然后在你的 dispatch_async 中添加,在你定义 retval 之后

variable = YES;

您只需在块之前定义 __block BOOL variable = NO;

【讨论】:

  • 不惜一切代价避免等待,在这种情况下没有必要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2011-04-10
  • 2022-01-26
  • 1970-01-01
相关资源
最近更新 更多