我希望同时获得三个请求以提高性能。 这是我当前的代码,它在我的tableview上只返回一个平台:
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.myapp.myqueue", DISPATCH_QUEUE_CONCURRENT);
void(^block_readPS4)() = ^{
self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"ps4"]];
};
void(^block_readXONE)() = ^{
self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"xboxone"]];
};
void(^block_readPC)() = ^{
self.releasesDict = [NSDictionary dictionaryWithDictionary:[self getDataWithPlatform:@"pc"]];
};
void(^block_write)() = ^{dictionaryWithDictionary:self.releasesDict];
self.releasesArr = [self.releasesDict allKeys];
[self.tableView reloadData];
[self.activityInd stopAnimating];
};
dispatch_async(concurrentQueue,block_readPS4);
dispatch_async(concurrentQueue,block_readXONE);
dispatch_async(concurrentQueue,block_readPC);
dispatch_barrier_async(concurrentQueue, block_write);
我知道问题是写在self.releasesDict,它是如何改进的?
答案 0 :(得分:4)
@ryancrunchi是正确的:
你在每次阅读中都会覆盖self.releasesDict。所以在你的写作中 阻止self.releasesDict的值将是最后一次读取的 系统执行。
...但是他提出的解决方案并不能保护字典免于并发写入,NSMutableDictionary
本质上不是线程安全的。您必须保护它免受并发读取和写入和/或写入+写入。这是您可能采用的一种方式(详细介绍了评论中所做的一切):
// A local (non-shared) mutable dictionary. Using a local dictionary allows us to know that no one
// else is reading from or writing to it concurrently, which is not guaranteed if we use self.releasesDict
NSMutableDictionary* localDict = [NSMutableDictionary dictionary];
// Your original concurrent queue
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.myapp.myqueue", DISPATCH_QUEUE_CONCURRENT);
// A serial queue to protect localDict from reading and writing.
dispatch_queue_t localDictWriteQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
// Make this queue target the concurrent queue. Not strictly required, but you had everything executing on
// concurrentQueue before, and this preserves that, while also protecting localDict.
dispatch_set_target_queue(localDictWriteQueue, concurrentQueue);
// A dispatch group that allows us to perform an operation only after all the constituent writes have finished.
dispatch_group_t group = dispatch_group_create();
// For each platform, enter the group, then fire off the concurrent block
dispatch_group_enter(group);
dispatch_async(concurrentQueue, ^{
// Fetch into a dictionary that is local to the block.
NSDictionary* x = [self getDataWithPlatform:@"ps4"];
// Then, on the serial localDictWriteQueue merge those entries into the shared local dictionary
dispatch_async(localDictWriteQueue, ^{
[localDict addEntriesFromDictionary: x];
// This balances out the dispatch_group_enter operation we did right before we enqueued this
dispatch_group_leave(group);
});
});
// Second verse, same as the first
dispatch_group_enter(group);
dispatch_async(concurrentQueue, ^{
NSDictionary* x = [self getDataWithPlatform:@"xboxone"];
dispatch_async(localDictWriteQueue, ^{
[localDict addEntriesFromDictionary: x];
dispatch_group_leave(group);
});
});
// Third verse, same as the first
dispatch_group_enter(group);
dispatch_async(concurrentQueue, ^{
NSDictionary* x = [self getDataWithPlatform:@"pc"];
dispatch_async(localDictWriteQueue, ^{
[localDict addEntriesFromDictionary: x];
dispatch_group_leave(group);
});
});
// Then set up the block we want to run at the end... use main queue because it updates UI.
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// Update self.releasesDict all at once, on the main thread
// Note: we do not need to do this read of localDict on localDictWriteQueue because if this block is executing, we know (semantically) that all possible
// write operations have already completed, and that no other writes to localDict are possible because it's local to this method call.
self.releasesDict = localDict;
// Same idea
self.releasesArr = [self.releasesDict allKeys];
// Update UI based on state changes to self.
[self.tableView reloadData];
[self.activityInd stopAnimating];
});
答案 1 :(得分:1)
您在每次阅读中都会覆盖self.releasesDict
。因此,在您的写入块中,self.releasesDict
的值将是系统执行的最后一次读取。如果您希望在同一个NSDictionary中读取所有内容,请将self.releasesDict
声明为NSMutableDictionary
并使用以下命令初始化:
self.releasesDict = [NSMutableDictionary dictionary];
并在你的阅读中:
[self.releasesDict addEntriesFromDictionary:[NSDictionary dictionaryWithDictionary:/*what you want*/]];