NSThread просыпается

Я хотел бы знать, как я могу добиться следующего в target-c,

Я взаимодействую с модемом FTDI232R, используя последовательную связь, поэтому я использую вызов POSIX для открытия, записи и чтения с пути модема (dev/tty/nameOfModem). Вызовы POSIX являются синхронными вызовами, поэтому во время чтения я не хочу блокировать свой основной поток, поэтому я думаю сделать вызов чтения в отдельном потоке.

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

Заранее благодарим вас за вашу помощь.


person subhash Amale    schedule 19.09.2014    source источник


Ответы (2)


Обычно у вас есть BOOL для обозначения вашего состояния выполнения, а затем дата, до которой нужно работать. Когда я делаю вещи с сокетами, я обычно делаю что-то вроде:

NSDate *beforeDate = [NSDate dateWithTimeIntervalSinceNow:.1];
while (self.isActive && [[NSRunLoop currentRunLoop] runMode: NSRunLoopCommonModes beforeDate:beforeDate]) {
    beforeDate = [NSDate dateWithTimeIntervalSinceNow:.1];
}

И затем, когда вы отключаетесь от модема, вы можете установить для isActive значение NO, чтобы запустить цикл выполнения.

Хотя это и не совсем то, что вам нужно, документы Apple на потоки с NSOperation могут быть интересны для вас.

person zadr    schedule 19.09.2014

Вероятно, вам следует использовать источники отправки GCD для этого. Вот пример кода, скопированный прямо из этой статьи:

dispatch_source_t ProcessContentsOfFile(const char* filename)
{
   // Prepare the file for reading.
   int fd = open(filename, O_RDONLY);
   if (fd == -1)
      return NULL;
   fcntl(fd, F_SETFL, O_NONBLOCK);  // Avoid blocking the read operation

   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ,
                                   fd, 0, queue);
   if (!readSource)
   {
      close(fd);
      return NULL;
   }

   // Install the event handler
   dispatch_source_set_event_handler(readSource, ^{
      size_t estimated = dispatch_source_get_data(readSource) + 1;
      // Read the data into a text buffer.
      char* buffer = (char*)malloc(estimated);
      if (buffer)
      {
         ssize_t actual = read(fd, buffer, (estimated));
         Boolean done = MyProcessFileData(buffer, actual);  // Process the data.

         // Release the buffer when done.
         free(buffer);

         // If there is no more data, cancel the source.
         if (done)
            dispatch_source_cancel(readSource);
      }
    });

   // Install the cancellation handler
   dispatch_source_set_cancel_handler(readSource, ^{close(fd);});

   // Start reading the file.
   dispatch_resume(readSource);
   return readSource;
}
person Ken Thomases    schedule 19.09.2014
comment
Спасибо за ваш ответ и код. У меня есть вопрос о коде, а именно, будет ли этот код или блок вызываться всякий раз, когда в файле есть данные для чтения? - person subhash Amale; 20.09.2014
comment
Код не блокирует. Когда в дескрипторе файла есть данные, доступные для чтения, блок обработчика событий источника отправки будет отправлен в очередь, указанную при создании источника. В данном примере это одна из глобальных параллельных очередей. Кроме того, дескриптор файла был установлен в неблокирующий режим, поэтому даже вызов read() в блоке обработчика событий не блокируется. Если нет доступных данных, он вернет -1 и установит errno в EAGAIN или EWOULDBLOCK. Этого не должно происходить, потому что источник не вызвал бы обработчик события, поэтому здесь он не обрабатывается. - person Ken Thomases; 20.09.2014