更新UI元素而不调度到主队列

时间:2018-08-23 17:09:42

标签: ios objective-c uikit grand-central-dispatch

我有一个dispatch_block_t,它传递给另一个功能,并且功能完成后,将调用此异步任务。但是问题是我不知道哪个线程将被调用。

我想在主线程中更新UI,因此我想使用

dispatch_async(dispatch_get_main_queue(), ^{...})

更新我的用户界面。但是,如果发生这种情况,恐怕会导致死锁

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
    dispatch_async(queue, ^{
        // outer block is waiting for this inner block to complete,
        // inner block won't start before outer block finishes
        // => deadlock
    });

    // this will never be reached
}); 

是否可以防止死锁?就像不使用dispatch queue来更新UI元素一样。是否可以创建weak referenceself来更新UI?

1 个答案:

答案 0 :(得分:1)

尝试使用NSLogs运行示例,您会发现不会发生死锁。这是由于以下事实:使用dispatch_async只是将一个块提交到队列中,而无需等待其完成执行(与dispatch_sync相反)。

因此运行以下代码:

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    NSLog(@"3");
});

将产生以下日志:

Testtt[32153:2250572] 1
Testtt[32153:2250572] 3
Testtt[32153:2250572] 2

此外,我担心这里使用dispatch_async(dispatch_get_main_queue(), ^{...})是一种常用技术,该技术可确保使用者在主线程上获得结果(即,使用者无需“关心”线程)。

但是,为什么使用dispatch_block_t来传递完成块呢?在我看来,在消费者端使用类似的东西有点令人困惑-我将传递一个匿名(没有typedef)块或为这些简单的完成块创建自己的typedef。