对Cocoa中新建线程的一点点理解

在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]; 


newThread:就是我们要创建的线程。它需要一个参数,返回值为空。

-(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的应用程序主线程会自动运行它的运行循环(run loop),除此之外的线程(或 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掉。

这样,主线程唯一保有work的引用,不会造成内存泄露。

    [(id)[serverConnection rootProxy] setServer: workerObject]; 
    [workerObject release];


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值