Ios Grand Central Dispatch中线程限制的解决方法?
有了它,您可以轻松地在非主线程上执行耗时的任务,避免阻塞主线程,并保持UI的响应性。只需使用Ios Grand Central Dispatch中线程限制的解决方法?,ios,objective-c,grand-central-dispatch,Ios,Objective C,Grand Central Dispatch,有了它,您可以轻松地在非主线程上执行耗时的任务,避免阻塞主线程,并保持UI的响应性。只需使用dispatch\u async并在全局并发队列上执行任务 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // code }); 然而,像这样听起来太好而不真实的事情通常也有其缺点。在我们的iOS应用程序项目中大量使用了它之后,最近我们发现它有64个线程的限制。一旦我们达到极限,应
dispatch\u async
并在全局并发队列上执行任务
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// code
});
然而,像这样听起来太好而不真实的事情通常也有其缺点。在我们的iOS应用程序项目中大量使用了它之后,最近我们发现它有64个线程的限制。一旦我们达到极限,应用程序将冻结/挂起。通过使用Xcode暂停应用程序,我们可以看到主线程由信号量\u wait\u trap
控制
谷歌在网上的搜索证实,其他人也遇到了这个问题,但到目前为止还没有找到解决办法
已达到调度线程硬限制:64(调度线程太多
在同步操作中被阻塞)
确认在使用dispatch\u sync
和dispatch\u barrier\u async
时也会发生此问题
问题:由于Grand Central Dispatch有64个线程的限制,是否有解决方法
提前谢谢 > P> >如果你有约束和决心,你可以释放你自己的GCD枷锁,然后使用pTrx走到每一个进程的线程限制上,正好相反,但是底线是这样的:如果你在GCD中遇到队列宽度限制,你可能会考虑重新评估你的并发方法。 在极端情况下,有两种方法可以达到极限:
in_port_t port = 10000;
void DieWithError(char *errorMessage);
// Returns a block you can call later to shut down the server -- caller owns block.
dispatch_block_t CreateCleanupBlockForLaunchedServer()
{
// Create the socket
int servSock = -1;
if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
DieWithError("socket() failed");
}
// Bind the socket - if the port we want is in use, increment until we find one that isn't
struct sockaddr_in echoServAddr;
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
do {
printf("server attempting to bind to port %d\n", (int)port);
echoServAddr.sin_port = htons(port);
} while (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0 && ++port);
// Make the socket non-blocking
if (fcntl(servSock, F_SETFL, O_NONBLOCK) < 0) {
shutdown(servSock, SHUT_RDWR);
close(servSock);
DieWithError("fcntl() failed");
}
// Set up the dispatch source that will alert us to new incoming connections
dispatch_queue_t q = dispatch_queue_create("server_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_source_t acceptSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, servSock, 0, q);
dispatch_source_set_event_handler(acceptSource, ^{
const unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
for (unsigned long i = 0; i < numPendingConnections; i++) {
int clntSock = -1;
struct sockaddr_in echoClntAddr;
unsigned int clntLen = sizeof(echoClntAddr);
// Wait for a client to connect
if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) >= 0)
{
printf("server sock: %d accepted\n", clntSock);
dispatch_io_t channel = dispatch_io_create(DISPATCH_IO_STREAM, clntSock, q, ^(int error) {
if (error) {
fprintf(stderr, "Error: %s", strerror(error));
}
printf("server sock: %d closing\n", clntSock);
close(clntSock);
});
// Configure the channel...
dispatch_io_set_low_water(channel, 1);
dispatch_io_set_high_water(channel, SIZE_MAX);
// Setup read handler
dispatch_io_read(channel, 0, SIZE_MAX, q, ^(bool done, dispatch_data_t data, int error) {
BOOL close = NO;
if (error) {
fprintf(stderr, "Error: %s", strerror(error));
close = YES;
}
const size_t rxd = data ? dispatch_data_get_size(data) : 0;
if (rxd) {
// echo...
printf("server sock: %d received: %ld bytes\n", clntSock, (long)rxd);
// write it back out; echo!
dispatch_io_write(channel, 0, data, q, ^(bool done, dispatch_data_t data, int error) {});
}
else {
close = YES;
}
if (close) {
dispatch_io_close(channel, DISPATCH_IO_STOP);
dispatch_release(channel);
}
});
}
else {
printf("accept() failed;\n");
}
}
});
// Resume the source so we're ready to accept once we listen()
dispatch_resume(acceptSource);
// Listen() on the socket
if (listen(servSock, SOMAXCONN) < 0) {
shutdown(servSock, SHUT_RDWR);
close(servSock);
DieWithError("listen() failed");
}
// Make cleanup block for the server queue
dispatch_block_t cleanupBlock = ^{
dispatch_async(q, ^{
shutdown(servSock, SHUT_RDWR);
close(servSock);
dispatch_release(acceptSource);
dispatch_release(q);
});
};
return Block_copy(cleanupBlock);
}
in_port\u t port=10000;
无效DIEWERROR(字符*错误消息);
//返回一个块,您可以稍后调用该块以关闭服务器--调用方拥有该块。
dispatch_block_t CreateCleanupBlockForLaunchedServer()
{
//创建套接字
int servSock=-1;
if((servSock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
DIEWERROR(“套接字()失败”);
}
//绑定套接字-如果我们想要的端口正在使用,则递增,直到找到一个未使用的端口
echoServAddr中的结构sockaddr_;
memset(&echoServAddr,0,sizeof(echoServAddr));
echoServAddr.sin_family=AF_INET;
echoServAddr.sin_addr.s_addr=htonl(INADDR_ANY);
做{
printf(“服务器试图绑定到端口%d\n”,(int)端口);
echoServAddr.sinu端口=htons(端口);
}而(bind(servSock,(struct sockaddr*)和echoServAddr,sizeof(echoServAddr))<0&&++port);
//使插座不阻塞
如果(fcntl(servSock、F_SETFL、O_NONBLOCK)<0){
停机(servSock,停机(RDWR));
关闭(servSock);
DIEWERROR(“fcntl()失败”);
}
//设置调度源,以提醒我们新的传入连接
调度队列q=调度队列创建(“服务器队列”,调度队列并发);
dispatch\u source\u t acceptSource=dispatch\u source\u create(dispatch\u source\u TYPE\u READ,servSock,0,q);
调度\u源\u集\u事件\u处理程序(acceptSource^{
const unsigned long numPendingConnections=dispatch\u source\u get\u data(acceptSource);
for(无符号长i=0;i=0)
{
printf(“服务器套接字:%d已接受\n”,clntSock);
调度io t通道=调度io创建(调度io流,clntSock,q,^(int错误){
如果(错误){
fprintf(标准,“错误:%s”,标准错误(错误));
}
printf(“服务器套接字:%d关闭\n”,clntSock);
关闭(clntSock);
});
//配置频道。。。
调度低水位(通道1);
调度高水位(通道,最大尺寸);
//设置读取处理程序
调度io读取(通道,0,最大大小,q,^(布尔完成,调度数据,整数错误){
布尔关闭=否;
如果(错误){
fprintf(标准,“错误:%s”,标准错误(错误));
关闭=是;
}
const size\u t rxd=数据?调度数据获取大小(数据):0;
if(rxd){
//回声。。。
printf(“服务器套接字:%d已接收:%ld字节\n”,clntSock,(长)rxd);
//把它写下来;回音!
分派io写入(通道,0,数据,q,^(布尔完成,分派数据,int错误){});
}
否则{
关闭=是;
}
如果(关闭){
调度io关闭(通道,调度io停止);
调度发布(通道);
}
});
}
否则{
printf(“accept()失败;\n”);
}
}
});
//恢复源代码,以便我们准备好