如何处理使用GCD的NSStream运行循环调度带来的并发问题? [英] How to deal with concurrency issues brought by NSStream run loop scheduling using GCD?

查看:115
本文介绍了如何处理使用GCD的NSStream运行循环调度带来的并发问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下情况下,我创建一个GCD调度队列,并在其中调度 NSStream 到当前的 NSRunLoop ,按照它的规范要求它发出委托事件,然后使用 [[NSRunLoop currentRunLoop run] 使该线程运行。 p>

这会产生三种可能的情况:


  1. 在其中创建一个串行队列最初的写消息通过流发送,而其他写消息仅在 NSStream 对象存在委托回调的情况下发送,因为尝试写新消息时不遵守该模式(


  2. 创建并发队列,在其中可以将消息自由地写入流中,这将是失败的。 ,因为发送到队列的块将与运行run循环的块同时执行。但是,虽然理想的是使消息并发运行的循环同时进行,但当然并不需要在试图同时写入流的同时运行的队列中进行阻塞。


  3. 创建两个队列-一个负责保持运行循环活动并接收从流中读取的回调,另一个负责向流发送异步写入消息。这似乎很理想,但是 NSStream 文档似乎特别指出,不应尝试对预定线程之外的流进行读/写。


鉴于这些方案都不是理想的,如何解决这些问题?

解决方案

晚了聚会,但是您可以直接使用

  void CFReadStreamSetDispatchQueue(CFReadStreamRef流,dispatch_queue_t q); 
void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream,dispatch_queue_t q);

其中CFReadStreamRef可以采用桥接NSInputStream,而CFWriteStreamRef可以采用桥接NSOutputStream。这样,您根本就不必调度或取消调度运行循环,流将在后台运行。



Apple示例代码

  CFReadStreamSetDispatchQueue((__ bridge CFReadStreamRef)self.inputStream,self.queue);复制代码
CFWriteStreamSetDispatchQueue((__ bridge CFWriteStreamRef)self.outputStream,self.queue);

在Swift中,您可以直接调用以下函数:

  CFReadStreamSetDispatchQueue(inputStream,streamQueue)
CFWriteStreamSetDispatchQueue(outputStream,streamQueue)


I have the following situation where I create a GCD dispatch queue and in it I schedule an NSStream to the current NSRunLoop, as is required in its specification for it to emit delegate events, and then I make the run loop for that thread run using [[NSRunLoop currentRunLoop run].

This generates three possible scenarios:

  1. Create a serial queue in which an initial write message is sent through the stream and other write messages are only sent when there's a delegate callback from the NSStream object, as attempting to write new messages without respecting this pattern (this would be desirable) will fail as the queue is locked by the run loop running.

  2. Create a concurrent queue in which messages can be written to the stream freely, as blocks sent to the queue will be executed concurrently with the block that's running the run loop. However, while it is desirable to make writing messages and the run loop running concurrent, it certainly is not desirable to have to blocks in the queue running concurrently attempting to write at the same time to the stream.

  3. Create two queues -- one responsible for keeping the run loop alive and receive read-from-stream callbacks and another one for sending asynchronous write messages to the stream. This would seem ideal, however it seems that the NSStream documentation specifically states that one should not attempt to read/write to a stream outside the thread it is scheduled in.

Given these scenarios none of which are ideal, how to solve these problems?

解决方案

Late to the party, but instead of using runloops you can set the desired dispatch queue for your streams directly using

void CFReadStreamSetDispatchQueue(CFReadStreamRef stream, dispatch_queue_t q);
void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream, dispatch_queue_t q);

Where CFReadStreamRef can take a bridged NSInputStream and CFWriteStreamRef a bridged NSOutputStream. This way you don't have to schedule or unschedule runloops at all and your streams will run in the background.

Snippet from this Apple sample code:

CFReadStreamSetDispatchQueue((__bridge CFReadStreamRef) self.inputStream,  self.queue);
CFWriteStreamSetDispatchQueue((__bridge CFWriteStreamRef) self.outputStream, self.queue);

In Swift, you can just directly call the functions:

CFReadStreamSetDispatchQueue(inputStream, streamQueue)
CFWriteStreamSetDispatchQueue(outputStream, streamQueue)

这篇关于如何处理使用GCD的NSStream运行循环调度带来的并发问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆