在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. activity启动模式之singleInstance

    activity启动模式之singleInstance 一.简介 Log.d("C2", getTaskId()+"");里面的getTaskId()可以获取a ...

  2. python学习笔记(excel+unittest)

    准备先利用之前整理的python自带的unittest框架 整合excel 实现接口自动化测试功能 先看看excel表格设置: 下来是对excel获取的代码: #!/usr/bin/env pytho ...

  3. spring3: 表达式5.2 SpEL基础

    5.1  概述 5.1.1  概述 Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行 ...

  4. yii2: oralce中文,有的汉字是2个字节,有的汉字是3个字节

    yii2: oralce中文,有的汉字是2个字节,有的汉字是3个字节 请用mb_substr转成1个英文字节

  5. 关于绑定的C#代码+转换器

    BindingOperations.SetBinding(                exp, Expander.IsExpandedProperty,                new Bi ...

  6. Node.js小白开路(一)-- events篇

    时间或许可以说是以JS来理解世界的基础,针对于某一个情况对象会做出何种反应,反应之后会做出何种处理,以及这一事件衍生出来了哪一些变化. 大多数 Node.js 核心 API 都采用惯用的异步事件驱动架 ...

  7. 【git】不同协议的路径

    https https://github.com/yesuuu/ganLearn.git ssh git@github.com:yesuuu/ganLearn.git git@idc:ganLearn ...

  8. Flask 上下文管理-- (session,request,current_app的传递)--类似本地线程实现,以及多app应用

    Flask session,request,current_app的传递 请求上下文的作用 -- 封装请求相关得数据(request,session) 请求上下文 request session re ...

  9. android自定义view系列:认识activity结构

    标签: android 自定义view activity 开发中虽然我们调用Activity的setContentView(R.layout.activity_main)方法显示View视图,但是vi ...

  10. js 柯里化Currying

    今天读一篇博客的时候,看都有关柯里化的东西,由于好奇,特意查了一下,找到一篇比较好的文章,特意收藏. 引子先来看一道小问题:有人在群里出了到一道题目:var s = sum(1)(2)(3) .... ...