0

我要从数据库加载一些重要内容并显示在屏幕上。但同时有一个“plist to Database”保存的后台任务正在进行中。因此 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 就会卡住。

似乎是线程死锁的问题,但对此尚不清楚

请帮忙 !!

4

1 回答 1

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是您更新 UI 的地方。
于 2013-03-12T19:12:35.380 回答