在Cocoa 中创建线程使用NSThread类的detachNewThreadSelector: toTarget:withObject:方法

  1. NSPort *port1 = [NSPort port];
  2. NSPort *port2 = [NSPort port];
  3. NSArray *userInfo= nil;
  4. NSConnection* kitConnection = nil;
  5. kitConnection = [[NSConnection alloc] initWithReceivePort:port1 sendPort:port2];
  6. [kitConnection setRootObject:self];
  7. userInfo= [NSArray arrayWithObjects:port2, port1, nil];
  8. [NSThread detachNewThreadSelector:@selector(newThread:)
  9. 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)。

下面是示例代码:

  1. - (void)newThread:(id)userInfo
  2. {
  3. NSAutoreleasePool *pool;
  4. NSConnection *serverConnection;
  5. mySubThread *subThreadWorker;
  6. pool = [[NSAutoreleasePool alloc] init];
  7. serverConnection= [NSConnection
  8. connectionWithReceivePort:[userInfo objectAtIndex:0]
  9. sendPort:[userInfo objectAtIndex:1]];
  10. subThreadWorker = [[mySubThread alloc] init];
  11. [serverConnection setRootObject: self];
  12. //do something;
  13. do
  14. {
  15. [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
  16. beforeDate:[NSDate distantFuture]];
  17. } while (![subThreadWorker shouldExit]);
  18. [subThreadWorker release];
  19. [pool release];
  20. return;
  21. }

在 serverConnection= [NSConnection connectionWithReceivePort:[userInfo objectAtIndex:0] sendPort:[userInfo objectAtIndex:1]];完成之后,

要建立主线程和子线程之间的通信,还需要在//do something之前加上这样一句代码:

  1. [(id)[serverConnection rootProxy] setServer: subThreadWorker];

setServer:是主线程中的方法。

执行这个方法,是为子线程在主线程中设置一个代理。

这样,在主线程中,就可以通过这个代理,来响应和执行子线程中的一些消息了。

下面给出一个主线程中的setServer:的示例:

  1. - (void)setServer:(id)anObject
  2. {
  3. [anObject setProtocolForProxy:@protocol(WorkerMethods)];
  4. work = (id <WorkerMethods>)[anObject retain];
  5. return;
  6. }

其中,work就相当于子线程在主线程的代理。

在主线程中,只要使work作为子线程消息的接收者,就可以响应和执行子线程的消息啦。

至此,主线程和子线程之间的连接就建立起来了。

此外,需要注意的一点是:在setServer:中我们看到,传入的参数anObject是被retain了的。

因此,在子线程newThread:中,在调用了setServer:之后,可以将参数release掉。

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

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

cocoa 线程操作的更多相关文章

  1. winform 跨线程操作控件

    当进行winform的开发时,经常遇到用时比较久的操作,在传统的单线程程序中,用户必须等待这个耗时操作完成以后才能进行下一步的操作,这个时候,多线程编程就派上用场了,将这个耗时的操作放到一个新的子线程 ...

  2. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  3. WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)

    最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...

  4. C#跨线程操作控件

    1.首先通过按键创建子线程: 创建子线程,子线程调用changeText方法. private void btnOK_Click(object sender, EventArgs e) { Threa ...

  5. WinForm中跨线程操作控件

    在WinForm编程时会遇到通过后台线程操作界面的情况,直接在后台线程执行的方法中直接操作控件会报错,这时候就要使用跨线程方式间接操作控件.下面是两种实现方式.   1.采用定义delegate的方式 ...

  6. 线程操作案例--生产者与消费者,Object类对线程的支持

    本章目标 1)加深对线程同步的理解 2)了解Object类中对线程的支持方法. 实例 生产者不断生产,消费者不断消费产品. 生产者生产信息后将其放到一个区域中,之后消费者从区域中取出数据. 既然生产的 ...

  7. NSTimer 线程操作

    http://www.jianshu.com/p/0c050af6c5ee 2.NSTimer的创建与撤销必须在同一个线程操作.performSelector的创建与撤销必须在同一个线程操作.

  8. C# 跨线程操作控件(简洁)

                                              C# 跨线程操作控件 .net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生.解决此问题的方法有两个: 第一 ...

  9. 线程操作API

    线程操作API 1.currentThread 2.getId() .getName().getPriority().getStart.isAlive().isDaemon().isInterrupt ...

随机推荐

  1. yii2:如果获取config/web.php配置的值?

    return [ 'version' => '1.0.1', 'category-map' => [ 1 => '样式1', 2 => '样式2', 3 => '样式3' ...

  2. JavaScript中的两个“0” -0和+0

    JavaScript中的两个“0”(翻译)   本文翻译自JavaScript’s two zeros JavaScript has two zeros: −0 and +0. This post e ...

  3. 19-THREE.JS 深度材质

    <!DOCTYPE html> <html> <head> <title></title> <script src="htt ...

  4. MS SQL GUID

    (转自:http://blog.csdn.net/maonongwu/article/details/6327093) GUID介绍 GUID(Global unique identifier)全局唯 ...

  5. ios上传图片遇见了一个TimeoutError(DOM Exception 23)异常

    TimeoutError(DOM Exception 23):The operation timed out 百度了下,没发现解决办法

  6. HAWQ取代传统数仓实践(八)——维度表技术之角色扮演维度

    单个物理维度可以被事实表多次引用,每个引用连接逻辑上存在差异的角色维度.例如,事实表可以有多个日期,每个日期通过外键引用不同的日期维度,原则上每个外键表示不同的日期维度视图,这样引用具有不同的含义.这 ...

  7. virtual box 安装 centos 7 不能上网问题解决总结

    http://blog.csdn.net/u013264730/article/details/51146359 1.设置virtualbox 网络选项 [root@centos1 ~]# cat / ...

  8. 深入理解java虚拟机-第二章

    第2章 Java内存区域与内存溢出异常 运行数据区域 1.程序计数器(Program Counter Register) 是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器. 2.J ...

  9. Centos7下命令笔记-ls

    ls命令大概是linux下最常用的命令之一,ls是list的缩写.因为linux目录或者文件记录的信息实在太多,所以默认ls只显示非隐藏的目录以及文件名.ls直接执行不加参数时显示本目录下的档案名. ...

  10. 剑指offer-第四章解决面试题的思路(顺序打印矩阵)

    题目:输入一个矩阵,按照从外向里的顺序依次打印出每一个数.(画图让抽象的问题形象化) 思路:打印矩阵时,把每一层当做一个圈来打印,找到打印整个矩阵的截止条件. 从上图中我可以看到一个6*6的矩阵(长宽 ...