3

对不起这个问题的模糊标题,我想不出一个简洁的句子来解释我遇到的问题。

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

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

- (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该上下文中的唯一偏移量。

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

4

3 回答 3

3

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

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

撇开这些不谈,你问:

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

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

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

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

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

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

但是您已指定selfdelegatefor 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无需深入研究即可创建多个实例的方法into NSThread(GCD 或操作队列通常比 Migrating Away From Threads 更可取NSThread;请参阅并发编程指南中的Migrating Away From Threads)。

最后的观察。我知道你可以做多少并发网络请求(通常是 4 或 5 个)是有限制的,所以你也可能对使用太多NSURLConnection实例保持警惕。NSURLSessionGCDAsyncSocket

于 2014-03-27T11:53:55.077 回答
2

问题是你的参数requestMessageWithOffset:。您应该使用sender[@"thread_offset"]而不是[NSNumber numberWithInt:_thread_offset] . 也为thread_bytes. 对于回调,您应该查找GCDAsyncSocket protocol

于 2014-03-27T10:59:48.820 回答
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);
}); 
于 2015-03-21T06:29:51.147 回答