在后台线程上执行工作后写入NSOutputStream不起作用 [英] Writes to NSOutputStream after performing work on background thread don't work

查看:39
本文介绍了在后台线程上执行工作后写入NSOutputStream不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,经过一些初始处理后,该程序会通过NSStreams发送大文件.应用程序的流程是这样的:

I have a program that is sending large files over NSStreams after some initial processing. The flow of the application goes like this:

1)两台设备相互连接,打开其输入和输出流,并安排其运行循环:

1) Two devices connect to each other, open their input and output streams, and schedule their run loops:

    [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)服务器设备向客户端发送一条消息,指示一切正常,我们已经准备就绪.客户端会很好地收到此消息.

2) The Server device sends a message to client indicating everything is good to go and we're all ready. The Client receives this message just fine.

3)然后,客户端选择要发送到服务器的文件列表,然后单击发送".然后,客户端会剥离一个后台线程以获取一堆文件并将其全部压缩.这可能需要一分钟左右的时间.

3) The client then selects a list of files that it wants to send to the server and hits "send." The client then spins off a background thread to grab a bunch of files and zip them all up. This can take upwards of a minute or so.

- (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:"的调用通过进行以下调用来传递第一批信息:

4) The call to 'sendFileWithItem:' delivers the first burst of information by making the following call:

if([_outputStream hasSpaceAvailable])
{
    NSInteger written = [self.outputStream write:buffer maxLength:self.outputHeaderSize];

}

通过调用-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent

问题

我在这里看到的问题是,如果用于压缩这些文件的后台线程花费较长的时间,则写入数据的初始调用确实表明字节已写入流中,但是我从未收到任何调用放入-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent 中.服务器从不接收信息.大约30秒钟后的某个地方,写命令(我假设吗?)超时,客户端收到一个空字符串(不是我从服务器显式发送的),并且客户端的连接关闭.

The problem I'm seeing here is that if the background thread to zip up these files takes a longer amount of time, the initial call to write data DOES indicate that bytes were written to the stream, but I never receieve any calls into - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)streamEvent. The server never receives information. Somewhere around 30 seconds later the write command (I assume?) times out, the client receives an empty string (NOT sent explicitly by me from the server), and the client's connection closes.

如果我发送的文件压缩时间不长,则不会出现此问题.

If I send over a file that doesn't take long to zip up, I don't see this problem.

运行主线程上的所有内容(包括压缩过程)都无法解决问题(即使忽略它锁定UI的事实).这似乎可以排除线程问题,但这只是我现在要做的所有事情.

Running everything on the main thread - including the zipping process - does not resolve the problem (even if ignoring the fact that it locks up the UI). This would appear to rule out the threading being an issue, but it's all I have to go on right now.

我完全没有主意,希望有人能帮助我.

I'm completely out of ideas, I hope someone can help me.

注意:出于这个建议,我无法使用CocoaAsyncSockets库.

Note: In anticipation of this suggestion, I cannot use the CocoaAsyncSockets library.

推荐答案

万一有人偶然发现了这个东西,并且碰巧看到了我所看到的同一件事(并且认为同一件事就是问题):

In case anyone ever stumbles up on this and just happens to see the same thing I saw (and think the same thing is the problem):

问题不在于线程是否引起了问题-只是写这篇文章使我意识到自己是多么荒谬.问题似乎出在等待很长时间以接收数据之后,底层的TCP套接字超时了.我通过每秒发送一次心跳消息来解决该问题,该消息使套接字保持活动状态,直到我准备好开始实际发送数据为止.

The problem wasn't that the threading was causing issues - just writing that post made me realize how absurd I was being. The problem appears to have been that the underlying TCP sockets were timing out after waiting for so long to receive data. I solved the problem by sending out a heartbeat message once a second, which keeps the sockets alive until I'm ready to actually start sending data.

这篇关于在后台线程上执行工作后写入NSOutputStream不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆