0

我使用“SimpleFTPSample”来执行 ftp 请求以列出错误信息。部分代码如下:

- (void)_startReceive
{
 ......
    self.networkStream = (NSInputStream *) ftpStream;
    self.networkStream.delegate = self;
    [self.networkStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [NSTimer scheduledTimerWithTimeInterval:TIMEOUTFTP target:self
                                   selector:@selector(dealTimeOut:) userInfo:nil repeats:NO];
 ......
}

我还设置了一个 NSTimer 以在 TIMEOUTFTP 之后停止 networkStream,如果请求在我定义的 TIMEOUTFTP 内正确完成,networkStream 也将关闭。我在另一个地方使用该方法,如下所示:

- (void)downLoadData
{
    NSArray* receivedData;
    [ftpService _startReceive];

   //wait until the network is closed
    while (ftpService.isReceiving) {}

    receivedData = ftpService.dataArray;

    if([receivedData count] == 0) {
       NSLog(@"no data get");   
    }
    else {
       NSLog(@"get data number %d", [receivedData count]);
    }

}

情况是程序卡在“while (ftpService.isReceiving) {}”。我不熟悉多线程。可能是我不正确理解运行循环。有人可以告诉我为什么会发生这种情况以及如何实现我的目的吗?

4

1 回答 1

2

在让程序继续之前,您应该重新考虑是否真的要等待接收到的数据。相反,您应该将您的 UI 置于显示正在下载并限制用户可以执行的操作的状态,将控制权返回给应用程序的主事件循环,并让它在收到数据时调用您的委托方法。只有在收到数据后,您才应该解锁 UI 并继续下一步,无论是什么。

阻塞应用程序的主线程将导致糟糕的用户体验,并可能导致您的应用程序终止。

但是,如果你真的想这样做,你需要运行运行循环而不是忙着等待。就像是:

while (ftpService.isReceiving)
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

实际上,在这种情况下,您自己运行运行循环,您应该在此处和您安排流的位置使用不同的运行循环模式。默认的运行循环模式将包含来自其余框架的运行循环源,让它们从你自己的内部运行循环中触发是很危险的。只需使用可能对您的程序唯一的任意字符串作为模式。

运行循环是各种事件源和输入(和计时器)的集合。您的代码和框架的各个部分都将在运行循环中调度源。它们依赖于正在运行的运行循环,以便接收事件/输入/定时器触发并处理它们。通过不运行运行循环而只是忙于等待,您阻止了流从 FTP 连接接收数据并对其进行处理。

于 2012-05-13T06:13:58.127 回答