并行GCD

时间:2017-02-06 08:45:32

标签: ios multithreading asynchronous gcdasyncsocket

问题很简单,但我找不到合理的答案。 在像这样的代码中

dispatch_queue_t background_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL);

dispatch_async(background_queue, ^{
// do some stuff that takes a long time here...

    // follow up with some stuff on the main queue
    dispatch_async(dispatch_get_main_queue(), ^{
        // Typically updating the UI on the main thread.
    });

});

“background_queue”是并发队列,因此其中的任务将按顺序启动,但可能无法以相同的顺序完成。因此,我们可以在下载图像之前调用更新UI块。 更多说明将有所帮助,谢谢。

4 个答案:

答案 0 :(得分:1)

在这个例子中,两个GCD块将按顺序完成,因为外部块只会在长进程完成后调用内部块(更正确一点,它应该是dispatch_sync上的内部块)

这将保证顺序,因为后台线程将在即将完成之前调用主线程的gcd块,并且仅在长任务完成之后调用

dispatch_async(background_queue, ^{
// do some stuff that takes a long time here...

    // follow up with some stuff on the main queue
    dispatch_sync(dispatch_get_main_queue(), ^{ //should be sync not async, but in practice should have little impact if nothing happens after this block
        // Typically updating the UI on the main thread.
    });
});

这不会,因为两个gcd块将同时执行,并且不会等待彼此完成

dispatch_async(background_queue, ^{
// do some stuff that takes a long time here...
});
// follow up with some stuff on the main queue
dispatch_async(dispatch_get_main_queue(), ^{
   // Typically updating the UI on the main thread.
});

答案 1 :(得分:0)

嗯,我想在这个简短的回答中我无法完全解释GCD机制,但我会给出一个简短的总结:

串行并发队列:

  • 串行队列工作FIFO(先进先出)。
  • 并发队列不保证任务完成甚至启动的顺序。

然后,有两种方法可以将工作项排入队列: async sync 。这涉及呼叫将如何返回:

  • 异步调用通常会在工作项启动或完成之前返回。
  • 工作项完成后将返回同步调用。

例如,如果您将工作项同步排入当前队列,则会导致死锁。

但GCD还有更多的方法,例如你可以将工作项目分组并等到所有项目都完成,或者你可以开始"高优先级"工作项目将是首选。

答案 2 :(得分:0)

在长任务完成后,您回到主队列上。 我将向您展示一个我正在开发的应用程序中的示例:

- (void)coinRequest {
    dispatch_queue_t coinsQueue = dispatch_queue_create("getUserCoins", NULL);
    dispatch_async(coinsQueue, ^{
        EMGetUserCoinsRequest* request = [EMGetUserCoinsRequest new];
        __weak typeof(self) _self = self;
        [self putCurrentRequest:request];
        request.suppressLoadingView = YES;
        [BackEnd() performRequest:request force:YES onSuccess:^(EMGetUserCoinsResponse *response) {

            dispatch_async(dispatch_get_main_queue(), ^{

                // Update the UI
                if (response.coins.coins != NULL) {
                    _self.coinsLabel.text = [NSString stringWithFormat:@"%@", response.coins.coins];
                } else {
                    _self.coinsLabel.text = [NSString stringWithFormat:@"0"];
                }
          });

        } onApplicativeError:NULL onEnvironmentError:NULL];
    });
}

正如您所见,我有一个请求用户硬币的请求。由于UI必须保持响应,我使用bg队列。下载信息后,在" onSuccess"块我回到主线程以更新UI。

答案 3 :(得分:0)

在操场上玩!

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

import Foundation

var s0 = ""
var s1 = ""

let queue = DispatchQueue(label: "cq", attributes: .concurrent)


let worker0 = { ()->() in
    for i in 0..<5000 {
        if (i % 1000) == 0 {
                print(i / 1000, terminator: "", to: &s0)
        }
    }
}

let worker1 = { ()->() in
    for i in 0..<5000 {
        if (i % 1000) == 0 {
                print(i / 1000, terminator: "", to: &s1)
        }
    }
}

queue.async(execute: {
    worker0()
    worker0()
    worker0()
    worker0()
    print(s0, " all workers0 were executed serialy")
})

let dg = DispatchGroup()

queue.async(group: dg, execute: worker1)
queue.async(group: dg, execute: worker1)
queue.async(group: dg, execute: worker1)
queue.async(group: dg, execute: worker1)

dg.wait()

print(s1, " workers1 were executed concurrently")

它会打印类似

的内容
00101212323434041234  workers1 were executed concurently
01234012340123401234  all workers0 were executed serialy

分派到任何队列的执行块中写入的所有代码都按顺序执行&#34;