I have a task which is reading from a disk, potentially going to take quite some time, so don't want to do it in a main thread.. and what I want is to call a function X after reading from the disk. What is the best way to do this in iOS?
我有一个从磁盘读取的任务,可能需要一段时间,所以不想在主线程中执行..我想要的是从磁盘读取后调用函数X.在iOS中执行此操作的最佳方法是什么?
So far this is what I've tried:
到目前为止,这是我尝试过的:
NSInvocationOperation *processDataOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(readDisk:) object:nil];
[processDataOperation setQueuePriority:NSOperationQueuePriorityVeryHigh];
[processDataOperation setCompletionBlock:^(void){
NSMutableArray *feedItemsArray = [self generateFeedItemsFromDictionary:streamDiskData];
[self postFetchCompletedNotificationForDict:queryStringDict withFeedItems:feedItemsArray isFresh:NO];
}];
basically I am using NSInvocationOperation and then set it's completion block, however the issue is that in my completion block I need the result that is generated in readDisk. How do I access that in the completion block? It's nearly imposible right?
基本上我使用NSInvocationOperation然后设置它的完成块,但问题是在我的完成块中我需要在readDisk中生成的结果。如何在完成块中访问它?这几乎是不可能的吗?
2 个解决方案
#1
7
Using NSInvocations it is possible, but far more complicated than necessary, to achieve a trivial amount of work beyond the main thread.
使用NSInvocations可以实现超出主线程的大量工作,但远比必要复杂得多。
Both GCD and NSOperations can be used to implement a wide array of concurrency strategies. From an object-oriented perspective, NSOperations are more highly abstracted than CGD blocks, which makes them (imo) easier to "design" with, and potentially optimized beyond the scope of where I'm implementing them. GCD is lower-level: This makes interacting with it appear slightly more complicated (it really isn't), but people who are in to that sorta stuff will tell you that it is "more efficient" and carries "less overhead".
GCD和NSOperations都可用于实现各种并发策略。从面向对象的角度来看,NSOperations比CGD块更抽象,这使得它们(imo)更容易“设计”,并且可能超出我实现它们的范围。 GCD是较低级别的:这使得与它的交互看起来稍微复杂一点(实际上并非如此),但是那些参与其中的人会告诉你它“更有效”并且带来“更少的开销”。
My personal approach is to use NSOperations in scenarios where I have a designed/orchestrated concurrency pattern in my application, and use GCD for trivial concurrent/background operations.
我个人的方法是在我的应用程序中具有设计/协调的并发模式的场景中使用NSOperations,并使用GCD进行简单的并发/后台操作。
If all I need to do is fire some arbitrary task that is not relevant to the design but needs to be done in the background, I'd use CGD. That's what I'd probably use in this case:
如果我需要做的就是解雇一些与设计无关但需要在后台完成的任意任务,我会使用CGD。这就是我在这种情况下可能会使用的内容:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self readDisk];
NSMutableArray *feedItemsArray = [weakSelf generateFeedItemsFromDictionary:streamDiskData];
dispatch_sync(dispatch_get_main_queue(), ^{
//Call back to the main thread before performing/posting anything touching UIKit
[self postFetchCompletedNotificationForDict:queryStringDict withFeedItems:feedItemsArray isFresh:NO];
})
})];
#2
0
You could always use grand central dispatch to do your operation in the background instead.
您可以随时使用盛大的*调度来在后台执行操作。
Since it is a block you can just call the method normally and store the result. Then grab the main queue if you need to update any UI or do whatever you need to after completion.
由于它是一个块,您可以正常调用该方法并存储结果。如果您需要更新任何UI或完成后需要执行任何操作,请抓取主队列。
dispatch_queue_t queue = dispatch_queue_create("read disc", NULL);
dispatch_async(queue, ^{
result = [self readDisc];
dispatch_async(dispatch_get_main_queue(), ^{
//update UI or do whatever you need to do with the result of readDisc
});
});
dispatch_release(queue);
#1
7
Using NSInvocations it is possible, but far more complicated than necessary, to achieve a trivial amount of work beyond the main thread.
使用NSInvocations可以实现超出主线程的大量工作,但远比必要复杂得多。
Both GCD and NSOperations can be used to implement a wide array of concurrency strategies. From an object-oriented perspective, NSOperations are more highly abstracted than CGD blocks, which makes them (imo) easier to "design" with, and potentially optimized beyond the scope of where I'm implementing them. GCD is lower-level: This makes interacting with it appear slightly more complicated (it really isn't), but people who are in to that sorta stuff will tell you that it is "more efficient" and carries "less overhead".
GCD和NSOperations都可用于实现各种并发策略。从面向对象的角度来看,NSOperations比CGD块更抽象,这使得它们(imo)更容易“设计”,并且可能超出我实现它们的范围。 GCD是较低级别的:这使得与它的交互看起来稍微复杂一点(实际上并非如此),但是那些参与其中的人会告诉你它“更有效”并且带来“更少的开销”。
My personal approach is to use NSOperations in scenarios where I have a designed/orchestrated concurrency pattern in my application, and use GCD for trivial concurrent/background operations.
我个人的方法是在我的应用程序中具有设计/协调的并发模式的场景中使用NSOperations,并使用GCD进行简单的并发/后台操作。
If all I need to do is fire some arbitrary task that is not relevant to the design but needs to be done in the background, I'd use CGD. That's what I'd probably use in this case:
如果我需要做的就是解雇一些与设计无关但需要在后台完成的任意任务,我会使用CGD。这就是我在这种情况下可能会使用的内容:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self readDisk];
NSMutableArray *feedItemsArray = [weakSelf generateFeedItemsFromDictionary:streamDiskData];
dispatch_sync(dispatch_get_main_queue(), ^{
//Call back to the main thread before performing/posting anything touching UIKit
[self postFetchCompletedNotificationForDict:queryStringDict withFeedItems:feedItemsArray isFresh:NO];
})
})];
#2
0
You could always use grand central dispatch to do your operation in the background instead.
您可以随时使用盛大的*调度来在后台执行操作。
Since it is a block you can just call the method normally and store the result. Then grab the main queue if you need to update any UI or do whatever you need to after completion.
由于它是一个块,您可以正常调用该方法并存储结果。如果您需要更新任何UI或完成后需要执行任何操作,请抓取主队列。
dispatch_queue_t queue = dispatch_queue_create("read disc", NULL);
dispatch_async(queue, ^{
result = [self readDisc];
dispatch_async(dispatch_get_main_queue(), ^{
//update UI or do whatever you need to do with the result of readDisc
});
});
dispatch_release(queue);