Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在iOS中执行多线程?_Ios_Objective C_Multithreading_Gcdasyncsocket_Cocoaasyncsocket - Fatal编程技术网

如何在iOS中执行多线程?

如何在iOS中执行多线程?,ios,objective-c,multithreading,gcdasyncsocket,cocoaasyncsocket,Ios,Objective C,Multithreading,Gcdasyncsocket,Cocoaasyncsocket,很抱歉,这个问题的标题很模糊,我想不出一个简洁的句子来解释我的问题 基本上,我希望启动多个线程并传递一个具有线程特定值的对象,我可以在该上下文中使用该值。下面是实现这一点的代码 while (count < no_threads) { _thread_bytes = _file_length / no_threads; _thread_offset = count * _thread_bytes; NSDictionary *args = [NSDictionar

很抱歉,这个问题的标题很模糊,我想不出一个简洁的句子来解释我的问题

基本上,我希望启动多个线程并传递一个具有线程特定值的对象,我可以在该上下文中使用该值。下面是实现这一点的代码

while (count < no_threads) {
    _thread_bytes = _file_length / no_threads;
    _thread_offset = count * _thread_bytes;

    NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithInt:_thread_offset],@"thread_offset",
                          [NSNumber numberWithInt:_thread_bytes], @"thread_bytes",
                          [NSNumber numberWithInt:count], @"count", nil];

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(processServerThread:) object:args];
    [thread start];
    count++;
}
如果有N个线程正在处理,当我发送请求消息时,输入
\u thread\u offset
的值,例如,如果偏移量为0、2、4、8。它为一个线程显示0,为所有其他线程显示8,而在该上下文中,每个线程都应该有一个唯一的偏移量


另外,线程完成时是否有回调方法

问题在于
requestMessageWithOffset:
的参数。您应该使用
sender[@“thread\u offset”]
而不是
[NSNumber numberwhithint:\u thread\u offset]
。也适用于
线程\u字节

对于回调,您应该在
gcdasyncsocketprotocol

中查找,我不清楚为什么要创建这些线程。
GCDAsyncSocket
背后的整个要点就是为您执行异步套接字通信。似乎没有必要创建自己的线程,让每个线程都启动异步写入任务

事实上,当我阅读您的代码示例时,您的线程将在异步写入启动后立即终止(但很可能在写入完成之前),我认为这不是您的意图

撇开这一点不谈,你会问:

它为一个线程显示0,为所有其他线程显示8,而在该上下文中,每个线程都应该有一个唯一的偏移量

正如sahara108所指出的,您引用的是实例变量
\u thread\u offset
\u thread\u bytes
,而不是访问添加到传递给线程的字典中的值。您应该从传递给线程的字典中检索这些值

另外,线程完成时是否有回调方法

您可以观察
NSThreadWillExitNotification
(显然可以编写
willEndThread
方法):

显然,您还必须编写一个
willEndThread
方法

但是您已经将
self
指定为
GCDAsyncSocket
delegate
,因此,如果您正在寻找写请求的完成,您应该实现这些委托方法


查看
GCDAsyncSocket
源代码,他们似乎希望您使用串行队列。因此,如果您想让并发请求继续,可以尝试以下方法:

_thread_bytes = _file_length / no_threads;
for (int i = 0; i < no_threads; i++) {
    _thread_offset = i * _thread_bytes;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL success = [self processRequestWithOffset:_thread_offset byteCount:_thread_bytes];

        if (!success) {
            // do here whatever you want if the connection was unsuccessful
        }
    }
}
如果您想知道每个连接是否成功完成,只需实现相关的
GCDAsyncSocket
delegate方法

就我个人而言,我很想看看这是否比在打开管道的情况下正常发布数据快。我对
GCDAsyncSocket
的特性也不是很熟悉,所以我不知道他们不希望您使用并发队列是否有更深层次的原因,但是上面的方法可能是创建
GCDAsyncSocket
的多个实例,而不必深入研究
NSThread
(GCD或操作队列通常优于
NSThread
;请参阅《并发编程指南》中的)


最后一个观察结果。我知道,对于
NSURLConnection
nsursession
,您可以执行的并发网络请求数量是有限制的(通常为4或5个),因此您可能会担心使用太多的
GCDAsyncSocket
实例。

现在使用GCD来实现这一点,请看下面

步骤1:使用dispatch\u Queue\u Create创建队列 步骤2:添加块并调用dispatch\u async

dispatch_queue_t myQueue = dispatch_queue_create("My Queue", NULL);

dispatch_async(myQueue, ^{
    NSLog(@"Running code in secondary thread...");

    int value = 0;
    for (int i=0; i<100; i++) {
        for (int j=0; j<100; j++) {
            for (int n=0; n<100; n++) {
                value += j;
            }
        }
    }
    NSLog(@"From secondary thread: value = %d", value);
}); 
dispatch\u queue\t myQueue=dispatch\u queue\u create(“我的队列”,NULL);
调度异步(myQueue^{
NSLog(@“在次线程中运行代码…”);
int值=0;

对于(int i=0;首先要做的是阅读和理解GCD(大中央调度)的文档,如果您想对多个线程执行任何严肃的工作。创建NSThread而不是使用GCD很少是一个好主意。感谢您的澄清,我似乎错误地使用了GCDAsyncSocket。因此,如果我创建了N个套接字连接,如何确保写操作在正确的时间访问正确的值?@L如果可以,我很乐意提供帮助,但也许我们应该退后一步,您可以更新您的问题并描述您正在尝试做什么。我的回答只是解决了现有问题中的一个简单逻辑不一致问题(无需创建线程来启动已经异步的任务)。但更基本的问题是,为什么要与通常为HTTP请求保留的端口进行套接字级别的通信。这对我来说没有意义。此外,从代码示例推断,您正在尝试将文件块同时写入套接字。但我在套接字协议中没有看到任何不通知您的信息您正在编写的套接字。可能是您的请求方法封装了该套接字,但我无法确定。我根本无法理解您的代码示例,因此,也许您可以后退一步,描述您正在尝试执行的操作,然后我们可以帮您解决该问题。感谢您的帮助。我正在尝试通过ugh同时使用多个套接字。我正在使用基于类型-长度-值模式的自定义协议与Python服务器通信消息和数据。目前,它在一个套接字上运行良好,但我想将其扩展到所需的任何最佳连接。因此,问题是如何使用GCDAsyncSocket创建多个实例,一个d同时发送一定偏移量的字节范围。OP中的代码块也与文件下载部分有关。
_thread_bytes = _file_length / no_threads;
for (int i = 0; i < no_threads; i++) {
    _thread_offset = i * _thread_bytes;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        BOOL success = [self processRequestWithOffset:_thread_offset byteCount:_thread_bytes];

        if (!success) {
            // do here whatever you want if the connection was unsuccessful
        }
    }
}
- (BOOL)processRequestWithOffset:(NSInteger)offset byteCount:(NSInteger)byteCount
{    
    NSError *error;

    dispatch_queue_t queue = dispatch_queue_create("main_server_queue", NULL);

    GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:queue];

    if (![socket connectToHost:@"example.com" onPort:8080 error:&error]) {    
        NSLog(@"Error: couldn't connect to file server: %@", error);
        return NO;
    }

    NSData *message = [[self requestMessageWithOffset:@(offset)
                                             andBytes:@(byteCount)
                                    dataUsingEncoding:NSUTF8StringEncoding];

    [socket writeData:message withTimeout:SOCKET_TIMEOUT tag:TAG_FILE_REQUEST_WRITE];

    return YES;
}
dispatch_queue_t myQueue = dispatch_queue_create("My Queue", NULL);

dispatch_async(myQueue, ^{
    NSLog(@"Running code in secondary thread...");

    int value = 0;
    for (int i=0; i<100; i++) {
        for (int j=0; j<100; j++) {
            for (int n=0; n<100; n++) {
                value += j;
            }
        }
    }
    NSLog(@"From secondary thread: value = %d", value);
});