記錄一下閱讀gRPC的OC源碼時(shí)看到的問題
沒有暴露設(shè)置超時(shí)時(shí)間的接口
在GRPCCompletionQueue.m
里面可以看到相關(guān)代碼,可以看到超時(shí)時(shí)間是const,外部無法修改烈拒,相當(dāng)于一個(gè)默認(rèn)的超時(shí)時(shí)間
const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
同時(shí)下面的處理也有點(diǎn)囧
...
gpr_timespec deadline = (timeoutSecs < 0)
? gpr_inf_future(GPR_CLOCK_REALTIME)
: gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
while (YES) {
// The following call blocks until an event is available or the deadline elapses.
grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
GRPCQueueCompletionHandler handler;
switch (event.type) {
case GRPC_OP_COMPLETE:
handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
handler(event.success);
break;
case GRPC_QUEUE_TIMEOUT:
// Nothing to do here
break;
case GRPC_QUEUE_SHUTDOWN:
grpc_completion_queue_destroy(unmanagedQueue);
return;
default:
[NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
}
...
超時(shí)居然不做處理前方,理應(yīng)拋個(gè)錯(cuò)誤什么的吧
網(wǎng)絡(luò)線程完成后回調(diào)在主線程
在GRXConcurrentWriteable.m
中可以看到俩功,回調(diào)時(shí)都工作在UI線程
// Designated initializer
- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable {
if (self = [super init]) {
_writeableQueue = dispatch_get_main_queue();
_writeable = writeable;
}
return self;
}
- (void)enqueueSuccessfulCompletion {
dispatch_async(_writeableQueue, ^{
dispatch_once(&_alreadyFinished, ^{
// Cancellation is now impossible. None of the other three blocks can run concurrently with
// this one.
[self.writeable writesFinishedWithError:nil];
// Skip any possible message to the wrapped writeable enqueued after this one.
self.writeable = nil;
});
});
}
這種設(shè)計(jì)模式在AFN中有娘赴,在gRPC中也有憾儒,但是實(shí)際應(yīng)用中我認(rèn)為問題很大询兴。我個(gè)人認(rèn)為多線程編程的其中一個(gè)最佳實(shí)踐就是,哪個(gè)線程發(fā)起異步任務(wù)起趾,回調(diào)時(shí)就工作在哪個(gè)線程诗舰,這樣對于調(diào)用方是最安全的。