CFWriteStreamScheduleWithRunLoop иногда работает, иногда нет? - PullRequest
2 голосов
/ 09 декабря 2010

Я занимаюсь асинхронным программированием сокетов, и мой код работает в большинстве случаев, но иногда это не так.Суть в том, что я создаю пару сокетов, создаю потоки чтения и записи, а затем, когда я хочу что-то записать, я планирую это в цикле выполнения отдельного потока.Примерно так:

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 Ответ

1 голос
/ 12 декабря 2010

Я получил решение от "quinn the eskimo" на форумах Apple:

Проблема заключалась в том, что хост выполнялся в одном потоке, а CFHostRef использовался в других. Это плохо.

CFHost создание, выполненное в том же потоке (объект scomm.host, выше), решает проблему.

...