如何同时执行多个异步方法并在它们全部完成时获得回调?

How to execute multiple async methods concurrently and get a callback when they all have finished?

我编写了以下代码,但我不确定它是否按照预期的方式工作:

func loadAssets(assets: [String: [String]]) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) {
        let group = dispatch_group_create()
        for (assetType, ids) in assets {
            switch(assetType) {
            case Settings.imageAssetType:
                for id in ids {
                    dispatch_group_enter(group)
                    Assets.fetchImage(id) { _ in
                        dispatch_group_leave(group)
                    }
                }
            case Settings.soundAssetType:
                for id in ids {
                    dispatch_group_enter(group)
                    Assets.fetchSound(id) { _ in
                        dispatch_group_leave(group)
                    }
                }
            case Settings.jsonAssetType:
                for id in ids {
                    dispatch_group_enter(group)
                    Assets.fetchJSON(id) { _ in
                        dispatch_group_leave(group)
                    }
                }
            case default:
                for id in ids {
                    dispatch_group_enter(group)
                    Assets.fetchClip(id) { _ in
                        dispatch_group_leave(group)
                    }
                }
            }
        }
        dispatch_group_notify(group, main, self.assetsDidLoad)
    }
}

基本上,一种使用字典加载所有资产的方法,其键值在其键中包含资产类型,并将资产 ID 列表作为值。然后,我为每种类型的资产遍历所有这些资产 ID,并调用一种方法来获取资产。 (我不确定获取方法是否完全 运行 异步,它们可能也有部分代码是同步的,这些方法将加载资产)。

无论如何,我想做的是在所有这些获取方法都完成后调用方法 assetsDidLoad(),因此所有资产都已加载,这就是我尝试使用调度组功能的原因。但是,我对这个调度代码还很陌生,我不确定我现在所做的是否适合我的目的。

如果有人能指出这是否可以,或者我应该如何处理这个问题,我将不胜感激。我什至希望在 Objective-C.

中得到回应

谢谢!

您的代码看起来是正确的(假设您的所有 fetch 方法都能保证执行它们的代码块)。如果 assets 为空,您的通知块将立即触发。 dispatch_group_enterdispatch_group_leave只需要平衡,可以在队列中调用。

作为参考,这里是我用来测试一些不同情况的一些代码(在 Objective-C 中):

dispatch_queue_t queue = dispatch_queue_create("com.Test.TestQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, queue, ^
{
    sleep(3);
    printf("\nFirst done!");
});

dispatch_group_async(group, queue, ^
{
    sleep(1);
    printf("\nSecond done!");

    dispatch_group_enter(group);
    sleep(5);
    printf("\nNested done!");
    dispatch_group_leave(group);

});

dispatch_group_async(group, queue, ^
{
    sleep(2);
    printf("\nThird done!");
});

dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
    sleep(10);
    printf("\nAsync done!");
    dispatch_group_leave(group);
});

dispatch_group_notify(group, dispatch_get_main_queue(), ^
{
    printf("\nAll done!");

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Message" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
    [alertView show];
});

最后显示警报,在调试器中是这样的:

Second done!
Third done!
First done!
Nested done!
Async done!
All done!