Cocoaでの新規スレッドのほんの少しの理解
3601 ワード
Cocoaでスレッドを作成NSThreadクラスを使用したdetachNewThreadSelector:toTarget:withObject:メソッド
新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)を明示的に実行する必要があります.
サンプルコードは次のとおりです.
serverConnection=[NSConnection connectionWithReceivePort:[userInfo objectAtIndex:0]sendPort:[userInfo objectAtIndex:1]];完了後、
プライマリ・スレッドとサブスレッド間の通信を確立するには、//do somethingの前にこのようなコードを追加する必要があります.
setServer:プライマリ・スレッド内のメソッドです.
この方法を実行すると、サブスレッドのプライマリスレッドにエージェントを設定します.
これにより、プライマリ・スレッドでは、このエージェントによって、サブスレッド内のいくつかのメッセージに応答して実行することができます.
次に、プライマリ・スレッドのsetServerの例を示します.
ここで、workはサブスレッドのプライマリスレッドのエージェントに相当します.
プライマリスレッドでは,workをサブスレッドメッセージの受信者とすれば,サブスレッドのメッセージに応答して実行することができる.
これで,メインスレッドとサブスレッドとの間の接続が確立される.
また、setServer:では、入力されたパラメータanObjectがretainされていることに注意してください.
したがって、サブスレッドnewThread:では、setServer:を呼び出した後、パラメータreleaseを削除できます.
これにより、プライマリ・スレッドはワークの参照を一意に保持し、メモリの漏洩は発生しません.
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];