ios - 如何在 iOS 中实现多线程?

标签 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 调用选择器方法,并且还可以访问 GCDAsyncSocket 套接字,因此这会导致许多使用 thread_bytesthread_offset 的委托(delegate)方法调用。这是选择器方法。

- (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];
}

如果有 N 个线程正在处理,当我发送请求消息时 _thread_offset 的值,例如,如果偏移量为 0、2、4、8。对于一个线程,它显示 0 和 8对于所有其他线程,虽然它们在该上下文中都应该有一个唯一的偏移量。

还有,线程结束的时候有回调方法吗?

最佳答案

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

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

抛开这个,你问:

It shows 0 for one thread an 8 for all other threads, while they should have each a unique offset within that context.

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

Also, is there any callback method for when a thread finishes?

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

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

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

但是您指定了 self作为delegate对于 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
        }
    }
}

在哪里

- (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即可。委托(delegate)方法。

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

最后的观察。我知道 NSURLConnectionNSURLSession您可以执行多少个并发网络请求是有限制的(通常是 4 或 5 个),因此您可能会小心使用太多 GCDAsyncSocket实例也是如此。

关于ios - 如何在 iOS 中实现多线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22685076/

相关文章:

ios - UITableView行高不变

iphone - 程序在使用 NSLOG 以外的变量时收到 SIGABRT

iphone - ios :How to compare 2 NSdates with Different formats?

java - 复制 volatile ArrayList 的元素

iphone - 如何在 iOS 上每次打开唯一文件夹中的解压缩文件

iphone - iOS Link Binary with library 仅用于调试

android - [在应用程序运行时] 定期执行操作的最佳方式 - 处理程序?

python - 在python中生成一个包含套接字连接的QThread

ios - 如何在 Button 内将 cornerRadius 设置为 UIImage?

ios - 当我添加新值时,如何从另一个 viewController 重新加载 tableview?