Cocoaでの新規スレッドのほんの少しの理解

3601 ワード

Cocoaでスレッドを作成NSThreadクラスを使用したdetachNewThreadSelector:toTarget:withObject:メソッド
    NSPort *port1 = [NSPort port]; 
    NSPort *port2 = [NSPort port]; 
    NSArray *userInfo= nil; 
    NSConnection* kitConnection = nil; 
    kitConnection = [[NSConnection alloc] initWithReceivePort:port1 sendPort:port2]; 
    [kitConnection setRootObject:self]; 
     
    userInfo= [NSArray arrayWithObjects:port2, port1, nil]; 
    [NSThread detachNewThreadSelector:@selector(newThread:) 
                toTarget:target withObject:userInfo]; 

新Thread:作成するスレッドです.パラメータが必要で、戻り値が空です.
-(void)newThread:(id)userInfo
 
target:作成したスレッドでnewThreadのメッセージを受信するために使用されます.
userInfo:新しいスレッドのパラメータにプライマリスレッドが渡されます.
また,プライマリスレッドとサブスレッドのconnectionのport順序に注意する.
 
-(void)newThread:(id)userInfoで理解する必要があるのは、次のとおりです.
1)まず、自動リリースプールを作成する必要があります.
2)新規スレッドの実行中にtargetとuserInfoはretainであり,スレッド終了後に自動的にreleaseが落ちる.
3)targetがnewThreadを完了すると,スレッドはすぐに終了する.
4)後で通信できるようにスレッドをアクティブにするには、newThreadに次のように追加する必要があります.
      [[NSRunLoop  currentRunLoop] run];あるいはrunMode:beforeDate,runUntilDateなどである.
一般的に、アプリケーションはNSRunLoopクラスを作成および管理する必要はありません.各NSThreadには、アプリケーション・プライマリ・スレッドを含めて自動的に作成されるNSRunLoopオブジェクトがありますが、Application Kitを使用するアプリケーション・プライマリ・スレッドのみが自動的に実行されます.それ以外のスレッド(またはFoundation Kit tools)は、独自の実行サイクル(run loop)を明示的に実行する必要があります.
サンプルコードは次のとおりです.
- (void)newThread:(id)userInfo  
{   
    NSAutoreleasePool *pool;   
    NSConnection *serverConnection;   
    mySubThread *subThreadWorker; 
  
    pool = [[NSAutoreleasePool alloc] init]; 
  
    serverConnection= [NSConnection   
            connectionWithReceivePort:[userInfo objectAtIndex:0]   
            sendPort:[userInfo objectAtIndex:1]]; 
  
    subThreadWorker = [[mySubThread alloc] init];  
 
    [serverConnection setRootObject: self]; 

    //do something; 
   
     do   
    {   
       [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode   
               beforeDate:[NSDate distantFuture]];   
    } while (![subThreadWorker shouldExit]);
   
   [subThreadWorker release];   
   [pool release]; 
  
    return;   
}  

serverConnection=[NSConnection connectionWithReceivePort:[userInfo objectAtIndex:0]sendPort:[userInfo objectAtIndex:1]];完了後、
プライマリ・スレッドとサブスレッド間の通信を確立するには、//do somethingの前にこのようなコードを追加する必要があります.
    [(id)[serverConnection rootProxy] setServer: subThreadWorker]; 

setServer:プライマリ・スレッド内のメソッドです.
この方法を実行すると、サブスレッドのプライマリスレッドにエージェントを設定します.
これにより、プライマリ・スレッドでは、このエージェントによって、サブスレッド内のいくつかのメッセージに応答して実行することができます.
次に、プライマリ・スレッドのsetServerの例を示します.
- (void)setServer:(id)anObject 
{ 
    [anObject setProtocolForProxy:@protocol(WorkerMethods)]; 
    work = (id <WorkerMethods>)[anObject retain]; 
    return; 
}

ここで、workはサブスレッドのプライマリスレッドのエージェントに相当します.
プライマリスレッドでは,workをサブスレッドメッセージの受信者とすれば,サブスレッドのメッセージに応答して実行することができる.
これで,メインスレッドとサブスレッドとの間の接続が確立される.
 
また、setServer:では、入力されたパラメータanObjectがretainされていることに注意してください.
したがって、サブスレッドnewThread:では、setServer:を呼び出した後、パラメータreleaseを削除できます.
これにより、プライマリ・スレッドはワークの参照を一意に保持し、メモリの漏洩は発生しません.
    [(id)[serverConnection rootProxy] setServer: workerObject]; 
    [workerObject release];