Reputation: 3593
I am trying to assign all my tasks from different NSTimer to one queue, so the task could be completed one by one. When the task is completed, I will get notified through delegate from one of another class.
Update: Task
My app is trying to communicate with another device, but that device can only accept one task at a time, so I have to send one task to it each time, and make sure I have received the confirmation which indicates task has been completed, then I can ask it to do the next task.
I tried to use a BOOL to control the state of IDLE, SENDING status. BUT I can't make it synchronized, even I used the following code:
@property (atomic) BOOL ready2Send;
@end
@implementation ...
@synthesize ready2Send = _ready2Send;
- (BOOL)ready2Send
{
BOOL tmp;
@synchronized(self) {
tmp = _ready2Send;
}
return tmp;
}
- (void)setReady2Send:(BOOL)ready2Send
{
@synchronized(self){
if (_ready2Send != ready2Send) {
_ready2Send = ready2Send;
}
}
}
But it doesn't work, There is always a case this property will stay NO until dead.
So I started to consider about using a queue, dispatch_queue maybe. I need one queue for my UIViewController.
My Question is:
Thank u.
Upvotes: 4
Views: 2630
Reputation: 437622
Assuming that your "communicate with another device" happens asynchronously, there are two approaches:
In the completion of the one task, initiate the next task.
For example, you might have an NSMutableArray
of items to be sent to the other device:
@property (nonatomic, strong) NSMutableArray *itemsToSend;
Once you've populated this array, to start the process, you might do a
[self sendItem:itemsToSend[0]];
And when it's done, you can do something like:
[itemsToSend removeObjectAtIndex:0];
if ([itemsToSend count] > 0)
{
[self sendItem:itemsToSend[0];
}
The more elegant (though more complicated) approach is to subclass NSOperation
(see Defining a Custom Operation). You can, for example:
@interface TaskOperation ()
@property (nonatomic, readwrite, getter = isExecuting) BOOL executing;
@property (nonatomic, readwrite, getter = isFinished) BOOL finished;
@end
@implementation TaskOperation
@synthesize finished = _finished;
@synthesize executing = _executing;
- (id)init
{
self = [super init];
if (self) {
_executing = NO;
_finished = NO;
}
return self;
}
- (void)start
{
if (self.isCancelled) {
self.finished = YES;
return;
}
self.executing = YES;
// initiate your time consuming process here
// when it's done, have it call `[self complete]`
}
- (void)complete
{
self.executing = NO;
self.finished = YES;
}
- (void)setExecuting:(BOOL)executing
{
[self willChangeValueForKey:@"isExecuting"];
_executing = executing;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)setFinished:(BOOL)finished
{
[self willChangeValueForKey:@"isFinished"];
_finished = finished;
[self didChangeValueForKey:@"isFinished"];
}
- (BOOL)isConcurrent
{
return NO;
}
@end
Your process that initiates these send requests can then do something like:
// create a serial queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
TaskOperation *operation;
// create and submit the three operations
operation = [[TaskOperation alloc] init ...];
[queue addOperation:operation];
operation = [[TaskOperation alloc] init ...];
[queue addOperation:operation];
operation = [[TaskOperation alloc] init ...];
[queue addOperation:operation];
Note, I've added ellipses here after the init method, because generally in this scenario, you write your own custom init method that passes whatever information the operation needs to complete its task (e.g. name of what's being transferred, perhaps where it's being transferred to, etc.).
But hopefully you get the idea. You define an operation class to perform your task, you can then create a serial queue and submit your tasks, and they will be executed in order, one after another.
If your "communicate with another device" process happens synchronously, then it's even easier than this. (But then again, if it was happening synchronously, you probably wouldn't have been messing around with timers and status flags to start with.)
Upvotes: 6