如何同时执行多个异步方法并在它们全部完成时获得回调?
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_enter
和dispatch_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!
我编写了以下代码,但我不确定它是否按照预期的方式工作:
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_enter
和dispatch_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!