Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

do some work in the background and return the result

I'm trying to get the ID from a tag, using a library.

I came up with the following. the loop that's looks for a tag is done in the background and I get a correct result in tagAsString.

-(void) readTag {
    NSLog(@"readTag");
    unsigned char * tagUID = (unsigned char *) malloc(M1K_UID_SIZE * sizeof(char)); 
    //work to do in the background
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        ERR ret;
        while ((ret = scanner->IsTagAvailable(tagUID)) != ERR_TAG_AVAILABLE) {
            NSLog(@"ret: %d", ret);
        }


        //main thread
        dispatch_async( dispatch_get_main_queue(), ^{
            if(ret == ERR_TAG_AVAILABLE) {
                NSLog(@"tag available");
                NSString *tagAsString = [[[NSString alloc] initWithFormat:@"%x%x%x%x", tagUID[0],tagUID[1],tagUID[2],tagUID[3]] retain];

            }
        });
    });
}

I would like to be able to return that value so I would be able to call:

NSString * myTag = [self readTag];

is that possible ? Thanks for your help, Michael

like image 889
Themikebe Avatar asked May 17 '11 14:05

Themikebe


People also ask

What is the current recommend way to handle long running background tasks?

Recommended solutionScheduling deferred work through WorkManager is the best way to handle tasks that don't need to run immediately but which ought to remain scheduled when the app closes or the device restarts.

What is background processing used for?

A background process is a computer process that runs behind the scenes (i.e., in the background) and without user intervention. Typical tasks for these processes include logging, system monitoring, scheduling, and user notification.


1 Answers

It is possible, however the problem with returning a string from that function is that it would need to hold up your calling thread whilst you perform the work in the background - thus losing the benefit of the background thread. (dispatch_sync is what you would use to do that - however I would not recommend it).

When using blocks it is best to restructure your program to fit better with the asynchronous paradigm. When the work is complete it should notify whatever is waiting on the result by sending a message to it with the result. In your example you would put this in the block of code you dispatch on the main queue.

@interface TagManager
- (void)fetchTag;
- (void)tagFetched:(NSString *)tag;
@end

@implementation TagManager
- (void)fetchTag {
    // The following method does all its work in the background
    [someObj readTagWithObserver:self];
    // return now and at some point someObj will call tagFetched to let us know the work is complete
}

- (void)tagFetched:(NSString *)tag {
    // The tag read has finished and we can now continue
}
@end

Then your readTag function would be modified as so:

- (void)readTagWithObserver:(id)observer {
    ...
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        ...
        dispatch_async(dispatch_get_main_queue(), ^{
           if (tag is ok) {
                [observer tagFetched:tag];
           }
        });
    });                          
}

The main idea is that you need to split your processing up into two stages

  1. requesting that some work is done (fetchTag in my example)
  2. process the result when it finishes (tagFetched: in my example)
like image 102
jjwchoy Avatar answered Oct 21 '22 00:10

jjwchoy