поработать в фоновом режиме и вернуть результат - PullRequest
8 голосов
/ 17 мая 2011

Я пытаюсь получить идентификатор из тега, используя библиотеку.

Я придумал следующее.цикл, который ищет тег, выполняется в фоновом режиме, и я получаю правильный результат в 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];

            }
        });
    });
}

Я хотел бы иметь возможность вернуть это значение, чтобы я мог вызвать:

NSString * myTag = [self readTag];

это возможно?Спасибо за вашу помощь, Майкл

1 Ответ

12 голосов
/ 17 мая 2011

Возможно, однако проблема с возвратом строки из этой функции заключается в том, что ей потребуется задержать ваш вызывающий поток, пока вы выполняете работу в фоновом режиме - таким образом теряется преимущество фонового потока. (dispatch_sync - это то, что вы бы использовали для этого - однако я бы не рекомендовал это).

При использовании блоков лучше всего реструктурировать вашу программу, чтобы она лучше соответствовала асинхронной парадигме. Когда работа завершена, он должен уведомить всех, кто ожидает результата, отправив ему сообщение с результатом. В вашем примере вы должны поместить это в блок кода, который вы отправляете в основную очередь.

@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

Тогда ваша функция readTag будет изменена следующим образом:

- (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];
           }
        });
    });                          
}

Основная идея заключается в том, что вам нужно разделить обработку на два этапа

  1. запрос на выполнение некоторой работы (fetchTag в моем примере)
  2. обработать результат после его завершения (tagFetched: в моем примере)
...