如何在iOS中进行多线程?

时间:2014-03-27 10:39:58

标签: ios objective-c multithreading gcdasyncsocket cocoaasyncsocket

对于这个问题含糊不清的标题感到抱歉,我想不出一个简明的句子来解释我遇到的问题。

基本上我想启动多个线程并传递一个对象,该对象具有我可以在该上下文中使用的特定于线程的值。这是执行该操作的代码

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

每个线程使用正确的thread_bytesthread_offset调用selector方法,并且还可以访问GCDAsyncSocket套接字,这会导致许多委托方法调用使用{{1 }和thread_bytes。这是选择器方法。

thread_offset

如果正在处理N个线程,当我发送请求消息的值为- (void)processServerThread:(id)sender { NSError *err; dispatch_queue_t iQueue = dispatch_queue_create("main_server_queue", NULL); GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:iQueue]; if (![socket connectToHost:@"example.com" onPort:8080 error:&err]) { NSLog(@"Error: couldn't connect to file server...."); return; } NSData *message =[[self requestMessageWithOffset:[NSNumber numberWithInt:_thread_offset] andBytes:[NSNumber numberWithInt:_thread_bytes]] dataUsingEncoding:NSUTF8StringEncoding]; [socket writeData:message withTimeout:SOCKET_TIMEOUT tag:TAG_FILE_REQUEST_WRITE]; } 时,例如,如果偏移量为0,2,4,8。对于一个线程显示0,对于所有其他线程显示8线程,虽然它们应该在该上下文中具有唯一的偏移量。

此外,是否有线程完成时的回调方法?

3 个答案:

答案 0 :(得分:3)

我不清楚为什么你要创建这些线程。 GCDAsyncSocket后面的全部内容是为您进行异步套接字通信。似乎没有必要创建自己的线程,每个都启动异步写入任务。

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

除此之外,你问:

  

对于一个线程显示0,对于所有其他线程显示8,而在该上下文中它们应该具有唯一的偏移量。

正如sahara108指出的那样,您引用了实例变量_thread_offset_thread_bytes,而不是访问您添加到传递给线程的字典中的值。您应该从传递给线程的字典中检索这些值。

  

此外,是否有线程完成时的回调方法?

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

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEndThread:) name:NSThreadWillExitNotification object:nil];

你显然也必须写一个willEndThread方法。

但您已将self指定为delegate的{​​{1}},因此,如果您正在寻找写请求的完成,则应实施这些委托方法


浏览GCDAsyncSocket来源,看起来他们希望您使用串行队列。因此,如果您希望同时发出请求,可以尝试以下内容:

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

如果您想知道每个连接是否成功完成,只需实现相关的- (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; } 委托方法。

就个人而言,我有兴趣看看这是否比打开流水线的数据的正常发布更快。我也不是非常熟悉GCDAsyncSocket的特性,所以我不知道是否有更深层次的理由说明他们不希望你使用并发队列,但以上可能是一种创建GCDAsyncSocket的多个实例而无需深入研究GCDAsyncSocket的方法(GCD或操作队列通常优于NSThread;请参阅并发编程中的Migrating Away From Threads指南的)。

最后一个观察结果。我知道,对于NSThreadNSURLConnection,您可以执行的并发网络请求数量(通常为4或5)存在限制,因此您可能会担心使用过多的{{1}实例也是。

答案 1 :(得分:2)

问题是requestMessageWithOffset:的参数。您应该使用sender[@"thread_offset"]代替[NSNumber numberWithInt:_thread_offset] 。也适用于thread_bytes。 对于回调,您应该在GCDAsyncSocket protocol

中查找

答案 2 :(得分:0)

现在使用GCD实现这一目标,请看下面的

步骤1:使用dispatch_queue_create创建队列 步骤2:添加阻止并调用dispatch_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);
});