【问题标题】:NSThread waking upNSThread 唤醒
【发布时间】:2014-09-19 15:01:08
【问题描述】:

我想知道如何在objective-c中实现以下目标,

我正在使用串行通信与 FTDI232R 调制解调器进行通信,因此我使用 POSIX 调用从调制解调器的路径(dev/tty/nameOfModem)打开、写入和读取。 POSIX 调用是同步调用,因此在读取时我不想阻塞我的主线程,因此我正在考虑在单独的线程中进行读取调用。

我不希望这个辅助线程连续运行,但只有在有要读取的内容时才醒来,并且在读取完成后它应该休眠。我浏览了文档并阅读了有关向 NSRunLoop 提供输入源并添加那个runloop到辅助线程,但不知道怎么做。

提前感谢您的所有帮助。

【问题讨论】:

    标签: objective-c nsthread nsrunloop


    【解决方案1】:

    您通常有一个BOOL 来指示您的运行状态,然后是运行日期。在做socket-y的事情时,我倾向于做这样的事情:

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

    然后,当您与调制解调器断开连接时,您可以将 isActive 设置为 NO 以让 runloop 停止运行。

    虽然不是完全您想要的,但 Apple 在 threading with NSOperation 上的文档可能会让您感兴趣。

    【讨论】:

      【解决方案2】:

      您可能应该为此使用GCD dispatch sources。以下是直接从那篇文章中复制的示例代码:

      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;
      }
      

      【讨论】:

      • 感谢您的回复和代码。我有一个关于代码的问题,即当文件中有数据要读取时,是否会调用此代码或块?
      • 代码不阻塞。当文件描述符上有数据可供读取时,调度源的事件处理程序块将提交到创建源时提供的队列。在此示例中,这是全局并发队列之一。此外,文件描述符已设置为非阻塞模式,因此即使事件处理程序块中的read() 调用也不会阻塞。如果没有可用数据,它将返回 -1 并将errno 设置为EAGAINEWOULDBLOCK。这不应该发生,因为源不会调用事件处理程序,所以这里没有处理。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 2016-04-17
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多