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_bytes各スレッドは、正しいおよびを使用してセレクター メソッドを呼び出し、ソケットにthread_offsetアクセスすることもできGCDAsyncSocketます。その結果、thread_bytesおよびを使用する多数のデリゲート メソッド呼び出しが発生します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 の場合、1 つのスレッドが 0、他のすべてのスレッドが 8 と表示されますそのコンテキスト内の一意のオフセット。

また、スレッドが終了したときのコールバック メソッドはありますか?

4

3 に答える 3

3

なぜこれらのスレッドを作成しているのか、私にはまったくわかりません。背後にある全体のポイントGCDAsyncSocketは、非同期ソケット通信を行うことです。独自のスレッドを作成し、それぞれに非同期書き込みタスクを起動させる必要はないようです。

実際、あなたのコード サンプルを読むと、スレッドは非同期書き込みが開始されるとすぐに終了します (ただし、おそらく書き込みが終了する前)。これはあなたの意図ではないと思います。

それはさておき、次のように尋ねます。

1 つのスレッドの場合は 0、他のすべてのスレッドの場合は 8 と表示されますが、そのコンテキスト内でそれぞれに一意のオフセットが必要です。

sahara108 が指摘したように、スレッドに渡した辞書に追加した値にアクセスするのではなく、インスタンス変数_thread_offsetを参照しています。_thread_bytesこれらの値は、スレッドに渡した辞書から取得する必要があります。

また、スレッドが終了したときのコールバック メソッドはありますか?

あなたは観察することができますNSThreadWillExitNotification(そして明らかにメソッドを書くことができますwillEndThread):

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

willEndThreadもちろん、メソッドも作成する必要があります。

ただし、 for として指定selfしたdelegateため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掘り下げずにの複数のインスタンスを作成する方法かもしれませんにNSThread(GCD またはオペレーション キューは、一般に よりも望ましいNSThreadです。Migrating Away From ThreadsConcurrency Programming Guideを参照してください)。

最後の観察。NSURLConnection同時に実行できるネットワーク リクエストの数には制限があること (通常は 4 または 5)を知っているので、あまりにNSURLSessionも多くのGCDAsyncSocketインスタンスを使用することには注意が必要かもしれません。

于 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 に答える