执行后台线程后写入NSOutputStream不起作用
我有一个程序在经过一些初始处理后通过NSStreams发送大文件。所述应用程序的流程是这样的:执行后台线程后写入NSOutputStream不起作用
1)两个设备彼此连接,打开它们的输入和输出流,并安排它们的运行循环:
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
2)所述服务器设备发送消息给客户指示一切都很好,我们都准备好了。客户收到这个消息就好了。
3)客户端然后选择它想要发送到服务器并点击“发送”的文件列表。客户端然后分离出一个后台线程来抓取一堆文件并将它们全部压缩。这可能需要一分钟左右的时间。
- (void) sendFilesAtPaths: (NSArray *) paths
{
self.paths = [paths copy];
__weak FileSharingClient *weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for(Item *item in weakSelf.paths)
{
//Zip files up, this can take some time but we're on a background thread so it won't lock up the UI
[weakSelf.connection zipFilesAssociatedWithItem:item];
}
//Now that we've done all the heavy work, bounce back to the main thread to actually start sending the data
dispatch_async(dispatch_get_main_queue(), ^{
//Start by sending only the first file, the server will let us know when they are ready for the next one
[weakSelf.connection sendFileWithItem:weakSelf.paths.firstObject];
});
});
}
4)所述的呼叫“sendFileWithItem:”通过使下面的调用提供的信息的第一脉冲串:
if([_outputStream hasSpaceAvailable])
{
NSInteger written = [self.outputStream write:buffer maxLength:self.outputHeaderSize];
}
所有下列数据由通过对- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent
的问题
我看到这里的问题是,我f后台线程压缩这些文件需要较长的时间,初始调用写入数据DOES表示字节已写入流中,但我从不接收任何拨入- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent
的电话。服务器从不接收信息。在大约30秒后的某个地方,write命令(我假设?)超时,客户端收到一个空字符串(不是由我从服务器明确发送的),并且客户端的连接关闭。
如果我发送的文件不需要很长时间就可以压缩,我不会看到这个问题。
在主线程上运行一切 - 包括压缩过程 - 并不能解决问题(即使忽略它锁定UI的事实)。这似乎排除了线程是一个问题,但现在我只需要继续。
我完全没有想法,我希望有人能帮助我。
注意:对于这个建议,我不能使用CocoaAsyncSockets库。
如果有人对这个曾经跌倒起来,恰好看到我看到了同样的事情(和想的一样东西是问题):
问题不在于该线程是造成问题 - 只是写这篇文章让我意识到我的存在是多么的荒谬。问题似乎是在等待这么长时间才能接收数据之后,底层的TCP套接字才会超时。我通过每秒发送一次心跳消息来解决问题,这使得套接字保持活动状态,直到我准备好开始发送数据。