CFWriteStreamScheduleWithRunLoop иногда работает, иногда нет?
Я занимаюсь асинхронным программированием сокетов, и мой код работает в большинстве случаев, но иногда это не так. Суть в том, что я создаю пару сокетов, создаю потоки чтения и записи, а затем, когда я хочу что-то записать, я планирую это в цикле выполнения отдельного потока. Вот так:
CFStreamClientContext context = {0, sc, NULL, NULL, NULL};
if (CFWriteStreamSetClient(sc.writeStream, kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, myWriteStreamCallBack, &context)) {
CFWriteStreamScheduleWithRunLoop(sc.writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}
... где myWriteStreamCallback - статическая функция правильной формы...
сокеты / потоки были открыты так:
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
@try {
// create a pair of streams to the host and open them
CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, scomm.host, SERVER_PORT, &readStream, &writeStream);
if (readStream == NULL) @throw [[[CommunicationReadStreamNotCreatedException alloc] init] autorelease];
if (writeStream == NULL) @throw [[[CommunicationWriteStreamNotCreatedException alloc] init] autorelease];
if (!CFReadStreamOpen(readStream)) @throw [[[CommunicationReadStreamNotOpenedException alloc] init] autorelease];
if (!CFWriteStreamOpen(writeStream)) @throw [[[CommunicationWriteStreamNotOpenedException alloc] init] autorelease];
...
Теперь о проблеме: этот код (и даже больше, если он кому-нибудь поможет) в основном корректен, потому что он в основном работает. Однако иногда, в самом начале программы, я могу попытаться отправить некоторые данные таким образом, и обратный вызов для сокета будет правильно помещен в цикл выполнения, но тогда он никогда не будет вызван. Позже в программе тот же код будет запущен с другим сокетом, и будет вызван обратный вызов (сокеты идут по тому же адресу).
Я знаю, что это расплывчато, но прежде чем я начну публиковать весь код, есть ли у кого-нибудь грубые идеи о вещах, которые потенциально могут вызвать это? То есть, обратные вызовы иногда не вызывались в runloops.
О да, я должен добавить, что это, очевидно, какой-то тип состояния гонки - я могу ненадежно устранить проблему, добавив в лог заявления в нужных местах. И потом, иногда это работает, а иногда нет, с точно таким же кодом. Весело весело.
1 ответ
Я получил решение от "Куин эскимос" на форумах Apple:
Проблема заключалась в том, что хост выполнялся в одном потоке, а CFHostRef
используется в других темах. Это плохо.
CFHost
создание сделано в той же теме (scomm.host
объект, выше) исправляет проблему.