我正在使用cryptotokenkit从智能卡发送/接收数据。用例是,在我做其他事情之前,我必须得到卡片API的响应。
在我的情况下,我发现在kMaxBlockingTimeSmartCardResponse(= 10)秒后总是调用此行。 来自
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
直接转到
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
然后等待10秒钟来阻止通话。它不是块回调延迟。如果我将调度时间设置为20或30秒,则等待20或30秒执行。等待调用确实等待指定的时间,然后执行回调块。
我做错了什么?我想知道这是否与adObserver有关。
- (void) updateSlots {
self.slotNames = [self.manager slotNames];
self.slotModels = [NSMutableArray new];
self.slots = [NSMutableArray new];
if([self.slotNames count] > 0)
{
for (NSString *slotName in self.slotNames)
{
NSLog(@"SmartCard reader found: %@", slotName);
// semaphore BLOCK starts
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self.manager getSlotWithName:slotName reply:^(TKSmartCardSlot *slot)
{
if (slot) {
SCSlotModel *slotModel = [SCSlotModel new];
[self.slotModels addObject:slotModel];
[self.slots addObject:slot];
[slot addObserver:self forKeyPath:@"state"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial
context:nil];
slotModel.suffixedName = slotName; // NOT slot.name; original name is suffixed with 01, 02 etc.
slotModel.slot = slot;
slotModel.cardStatus = [CardUtil mapCardStatus:slot.state];
DLog(@"slot: %@, slotmodel: %@",slot.name, slotModel);
} else {
NSLog(@"Did not find slot with name: %@", slotName);
}
dispatch_semaphore_signal(sema);
}];
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
// semaphore BLOCK ends
self.errorCode = SCPNoError;
}
} else {
NSLog(@"No slot available.");
self.errorCode = SCPErrorReaderNotFound;
}
}
getSlotWithName
是来自TKSmartCardSlotManager
/// Instantiates smartcard reader slot of specified name. If specified name is not registered, returns nil.
- (void)getSlotWithName:(NSString *)name reply:(void(^)(TKSmartCardSlot *__nullable slot))reply;
但在其他地方,它可以按预期工作,用于相同类型的异步调用。
- (BOOL) beginSession:(TKSmartCard *)card
{
__block BOOL response = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[card beginSessionWithReply:^(BOOL success, NSError *error) {
response = success;
if (!success) {
NSLog(@"Could not begin session.");
}
if (error) {
NSLog(@"Could not begin session with error %@", error);
}
dispatch_semaphore_signal(sema);
}];
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kMaxBlockingTimeSmartCardResponse * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
return response;
}
答案 0 :(得分:0)
getSlotWithName:reply:
重新调用其回复处理程序的线程是什么?
例如,如果在主线程上执行updateSlots
,并且您正在执行以下操作:
... // some async operation in `getSlotWithName:reply:` has completed
dispatch_async(dispatch_get_main_queue(), ^{
reply(slot)
});
然后你最终会在主线程上排队你的回复,但主线程目前已被你的信号量锁定。
确保从您锁定的线程以外的其他线程中调用dispatch_semaphore_signal()
可以解决您的问题。
侧注: GCD和信号量在这里做的伎俩,但有一些更好的方法可以在异步操作完成后执行操作,而不是让线程被锁定。例如,委托回调。
没有足够的信息在这里建议任何确切的,但还有其他选择:)