dispatch_async无法使用后台线程

时间:2012-09-03 16:05:15

标签: multithreading objective-c-blocks grand-central-dispatch dispatch-async

我有一些重要的内容要从数据库加载并显示在屏幕上。 但同时还有一个“plist to Data base”的后台任务正在进行中。 因此UI被卡住了。

我正在使用的代码,

对于数据库提取和UI更新方法

- (void)performBlockInBackground:(dispatch_block_t)taskBlock
                              completion:(dispatch_block_t)completionBlock
                            withPriotity:(dispatch_queue_priority_t)piority
{
    __block dispatch_block_t taskBlockRef = taskBlock;
    __block dispatch_block_t completionBlockRef = completionBlock;

    dispatch_async(dispatch_get_global_queue(piority, 0), ^{

        dispatch_sync(dispatch_get_global_queue(piority, 0), taskBlockRef);

        dispatch_async(dispatch_get_main_queue(), completionBlockRef);
    });
}

我将'Plist to DB'方法称为

[self performSelectorInBackground:@selector(syncData) withObject:nil];

此处taskBlock是重度数据库提取,completionBlock是UI更新。

如果我在一段时间后调用此方法(在syncData方法完成后),则它会顺利更新。但如果它尚未完成,那么UI就会卡住。

这似乎是线程死锁的问题,但在此

上并不清楚

请帮助!!

1 个答案:

答案 0 :(得分:3)

当您已经在正确的队列中时,您不需要dispatch_sync()。您可以像这样调用块:taskBlock()

- (void)performBlockInBackground:(dispatch_block_t)taskBlock
                    withPriority:(dispatch_queue_priority_t)priority
          completionOnMainThread:(dispatch_block_t)completionBlock
{
  dispatch_async(dispatch_get_global_queue(priority, 0), ^{
    if (taskBlock) {
      taskBlock();
    }

    if (completionBlock) {
      dispatch_async(dispatch_get_main_queue(), completionBlock);
    }
  });
}

这是怎么回事:

  • 立即将工作发送到后台线程。现在我们不会阻塞调用线程或主线程。
  • 如果我们有taskBlock,请立即执行。 TaskBlock是您提取数据的地方。
  • TaskBlock完成。
  • 如果我们有completionBlock,请将其发送到主线程。 CompletionBlock是您更新用户界面的地方。