记录一下阅读gRPC的OC源码时看到的问题
没有暴露设置超时时间的接口
在GRPCCompletionQueue.m
里面可以看到相关代码,可以看到超时时间是const,外部无法修改,相当于一个默认的超时时间
const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
同时下面的处理也有点囧
...
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];
}
...
超时居然不做处理,理应抛个错误什么的吧
网络线程完成后回调在主线程
在GRXConcurrentWriteable.m
中可以看到,回调时都工作在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;
});
});
}
这种设计模式在AFN中有,在gRPC中也有,但是实际应用中我认为问题很大。我个人认为多线程编程的其中一个最佳实践就是,哪个线程发起异步任务,回调时就工作在哪个线程,这样对于调用方是最安全的。