4

iOS 6.1.3 を使用する iPhone では、NSRunLoop を使用せずに outputStream に書き込もうとしています。私のストリームは、次のように単純に初期化されます。

    session = [[EASession alloc] initWithAccessory:accessory
                                       forProtocol:protocolString];
    if (session)
    {
        NSLog(@"opening the streams for this accessory");
        [[session inputStream] open];
        [[session outputStream] open];
        [session retain];
        streamReady = true;
        receivedAccPkt = true;
    }

次に、コードの他の場所で、次のようにデータを送信しようとすると:

uint8_t requestData[8] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
while (![[eas outputStream] hasSpaceAvailable]);
@synchronized(self) {
    len += [[eas outputStream] write:requestData maxLength:8];
}

「hasSpaceAvailable」メソッドが true を返さないため、コードがスタックしています。

データを送信するために、出力ストリームに対して実行する他の初期化タスクはありますか?

4

1 に答える 1

2

EASession のドキュメントには、ストリーム イベントを処理するデリゲートを割り当ててストリームを構成し、実行ループでスケジュールする必要があると記載されています。

実行ループを使用すると、スレッドを気にせずにストリームを駆動できます。たとえば、プロパティを介して出力ストリームに書き込む場合、書き込まれたバイトを取得するためにオブジェクトによって使用される内部入力ストリーム (パブリックに表示される出力ストリームにバインドされている)outputStreamが存在する可能性が非常に高くなります。この内部入力ストリーム (表示されない) も、公開されている出力ストリームと同じ実行ループを使用する場合があります。 EASessionoutputStream

内部入力ストリームとパブリック入力ストリームを一致させないでください! 基本的に、2 つの公開ストリームと 2 つの内部ストリームがあります。各パブリック ストリームには内部的にペンダントが関連付けられています。入力ストリームにはバインドされた出力ストリームがあり、出力ストリームにはバインドされた入力ストリームがあります。

ただし、(出力) ストリームに実行ループを使用することは避けることができます。メソッドがプライベートwrite:maxLength:スレッドで実行されることを保証するだけで済みます。プライベートスレッドは、 による内部ストリームでは使用されません。EASession

ディスパッチを利用するだけでプライベートスレッドを取得できます。以下のコードを試すことができます。

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [outputStream open];
    const char* data = ...;
    int dataLength = ...;
    while (dataLength && !isCancelled) {
        int written = [outputStream write:(const uint8_t*)data maxLength:1];
        if (written > 0) {
             dataLength -= written;
             data += written;
        }
        else if (written < 0 )
        {
            // error occurred
            break;
        }
    }
    [outputStream close];
});

注: への以前の呼び出しがwrite:maxLength:ゼロを返し、まだ書き込むデータがある場合、これはスレッドをブロックします。したがって、内部ストリームは同じスレッドを使用してはなりません。そうしないと、デッドロックが発生します。

スレッドがブロックされると、ブロックの解除が困難になります。おそらく、実行ループ アプローチを試す必要があります。

于 2013-11-04T16:13:46.410 に答える