GCDAsyncSocket 在接收数据时冻结 UI

Posted

技术标签:

【中文标题】GCDAsyncSocket 在接收数据时冻结 UI【英文标题】:GCDAsyncSocket freezes UI when receiving data 【发布时间】:2015-04-10 15:39:26 【问题描述】:

我是 GCD 原理和 GCDAsyncSocket 的新手,但我在我的项目中使用它。我在 AppDelegate 中初始化 GCD 套接字:

self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

现在,一切正常,发送和接收工作正常。但是,如果套接字非常快地接收到大量数据(例如来自服务器的“for循环”的大约 1000 条消息),则应用程序的 UI 会冻结,直到它接收到所有内容(尽管接收到的消息中没有错误) .

那么我需要进行哪些更改才能不让 UI 冻结?是因为它使用“dispatch_get_main_queue()”,我需要使用另一个队列吗?如果是这样,我应该怎么做?还是我使用线程或类似的东西?

【问题讨论】:

【参考方案1】:

尝试创建自己的并发串行后台队列(结果你不允许使用并发的),例如

dispatch_queue_t queue = dispatch_queue_create("com.yourid.queue", DISPATCH_QUEUE_SERIAL);
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue: queue];

您也可以传递“NULL”,GCDAsyncSocket 将创建自己的队列。

这应该调用后台队列中的委托方法,并希望阻止您的 UI 冻结。这里需要注意的重要一点是,您不能在后台队列中更新 UI 元素,因此您必须在委托方法中执行类似的操作:

- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port

    //Do some calculations (in background queue)

    dispatch_async(dispatch_get_main_queue(), ^
        //Update UI elements (in main queue)
    );
 

(希望我没记错)

【讨论】:

我阅读了 GCD 文档并自己解决了这个问题。唯一的区别是您创建的自定义调度队列是并发的,我相信 GCDAsyncSocket 委托队列需要是串行的(以便所有传入/传出消息一个接一个地串行处理)。因此,串行的在我的实现中运行良好,但我还没有测试并发的。如果您可以向我保证并发的也可以,我会将此答案标记为正确的。 我做了更多研究并编辑了我的答案。原来你不允许使用并发队列...

以上是关于GCDAsyncSocket 在接收数据时冻结 UI的主要内容,如果未能解决你的问题,请参考以下文章

无法接收使用 GCDAsyncSocket 发送的 UDP 数据包的响应

GCDAsyncSocket 未接收到所有传输的数据,缺少最后一个“块”

COM 自动化 Excel 2010 冻结

MPI_Recv() 冻结程序,未从 C 中的 MPI_Send() 接收值

没有同时读取数据GCDAsyncSocket

当我添加 UDP 代码时,pyqtgraph 和 python 冻结