在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. 【Python那些事儿之十】range()和xrange()

    by Harrison Feng in Python 无论是range()还是xrange()都是Python里的内置函数.这个两个内置函数最常用在for循环中.例如: >>> fo ...

  2. poj3468线段树标记永久化

    #include<map> #include<set> #include<list> #include<cmath> #include<queue ...

  3. Vue2基于Axios Ajax Vuex的Loading组件

    1. 定义根state:ajaxIsLoading2. 在Axios拦截器中commit不同的状态实现状态切换3. 组件中通过getter获取ajaxIsLoading状态 Axios 拦截器配置 i ...

  4. 006——VUE中的内容与属性中使用javascript表达式的方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Sqlite/ FMDB

    Sqlite 1. Sqlite数据库 > 数据库? 按数据结构来组织,存储和管理数据的仓库. > 关系型数据库:使用二维表及其之间的联系组织成一个数据组织. 关系:可以理解为一张二维表, ...

  6. 目标跟踪之ECO:Efficient Convolution Operators for Tracking

    一. 相关滤波算法总结 作者首先分析了 影响相关滤波算法效率 和 导致过拟合 的几个原因: 1)Model Size (模型大小) 包括两个方面: - 模型层数,对应多分辨率 Sample,比如多层 ...

  7. 给Java新手的一些建议——Java知识点归纳(Java基础部分)

    写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给 ...

  8. 官方:MySQL 5.7 并行复制实现原理与调优 | InsideMySQL(转载)

    MySQL 5.7并行复制时代 众所周知,MySQL的复制延迟是一直被诟病的问题之一,然而在Inside君之前的两篇博客中(1,2)中都已经提到了MySQL 5.7版本已经支持“真正”的并行复制功能, ...

  9. 火狐下的GreaseMonkey和Chrome下的tampermonkey使用手记

    说明:GreaseMonkey的作用是让我们浏览器运行我们自己写的脚本,而且是在后台一直不断的运行,听着就让人兴奋. [ps:他们当然可以创建名单对哪些网站作用或者排除哪些站点]: 开始了:Greas ...

  10. Android的长度单位及屏幕分辨率

    屏幕分辨率基础 1.术语和概念 术语 说明 备注 Screen size(屏幕尺寸) 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 摩托罗拉milestone手机 ...