4

Right now I'm working on a program using IOBluetooth and I need to have synchronous reads, i.e. I call a method, it writes a given number of bytes to the port, then reads a given number and returns them. I currently have a complex system of NSThreads, NSLocks, and NSConditions that, while it sort of works, is very slow. Also, after certain calls, I need to make sure there's no extra data, so I'd normally flush the buffer, but with IOBluetooth's asynchronous callback that's not possible - any thoughts on how to make sure that no matter what, all data received after a specific point is data that's received after that point?

I really haven't dealt at all with synchronization and multithreading of this type, since all the work I've done so far is using synchronous calls, so I'd appreciate any thoughts on the matter.

Here's the callback for incoming data (the "incomingData" object is NSMutableData):

- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength {
    [dataLock lock];
    NSData *data = [NSData dataWithBytes:dataPointer length:dataLength];
    [incomingData appendData:data];

    if (dataWaitCondition && [incomingData length] >= bytesToWaitFor) {
        [dataWaitCondition signal];
    }

    [dataLock unlock];
    [delegate bluetoothDataReceived];
}

And here's the method that waits until the given number of bytes has been received before returning the data object (this gets called from an alternate thread).

- (NSData *)waitForBytes:(int)numberOfBytes {

    bytesToWaitFor = numberOfBytes;
    [dataLock lock];
    dataWaitCondition = [[NSCondition alloc] init];
    [dataWaitCondition lock];
    [dataLock unlock];
    while ([incomingData length] < numberOfBytes) {
        [dataWaitCondition wait];
    }
    [dataLock lock];
    NSData *data = [incomingData copy];
    [dataWaitCondition unlock];
    dataWaitCondition = NULL;
    [dataLock unlock];

    return data;
}
4

1 回答 1

0

以同步方式进行任何类型的 IO/通信都会给您带来麻烦。

您可以通过对应用程序逻辑使用简单的状态机来避免多线程和锁定。每当接收到数据时,状态机就会被触发并可以处理数据。如果所有数据都在那里,您可以在应用程序中执行下一步。如果您愿意,您可以使用同步调用进行发送,因为它只会丢弃蓝牙系统的数据。

于 2011-09-22T15:34:51.033 回答