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];
 ......
}

また、TIMEOUTFTP 後に networkStream を停止するように NSTimer を設定しました。定義した 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.isRecoming) {}」でスタックすることです。私はマルチスレッドに慣れていません。実行ループを正しく理解していない可能性があります。なぜこれが起こるのか、そして私の目的を達成する方法を教えてもらえますか?

4

1 に答える 1

2

プログラムを続行する前に、受信したデータを本当に待つかどうかを再検討する必要があります。代わりに、UIをダウンロード中であることを示し、ユーザーが実行できることを制限する状態にし、アプリのメインイベントループに制御を戻し、データを受信したときにデリゲートメソッドを呼び出せるようにする必要があります。データを受信したら、UIのロックを解除して、次の手順に進む必要があります。

アプリのメインスレッドをブロックすると、ユーザーエクスペリエンスが低下し、アプリが終了する可能性があります。

ただし、本当にこれを実行したい場合は、ビジー待機を実行するのではなく、実行ループを実行する必要があります。何かのようなもの:

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

実際、実行ループを自分で実行しているこの場合は、こことストリームをスケジュールする場所の両方で異なる実行ループモードを使用する必要があります。デフォルトの実行ループモードには、残りのフレームワークからの実行ループソースが含まれ、独自の内部実行ループからそれらを起動させるのは危険です。そのモードのプログラムに固有である可能性が高い任意の文字列を使用するだけです。

実行ループは、イベントと入力(およびタイマー)のさまざまなソースのコレクションです。コードとフレームワークのさまざまな部分の両方が、実行ループでソースをスケジュールします。それらは、イベント/入力/タイマーファイアを受信して​​処理するために実行されている実行ループに依存します。実行ループを実行せず、ビジー待機するだけで、ストリームがFTP接続からデータを受信して​​処理するのを防ぐことができました。

于 2012-05-13T06:13:58.127 に答える