RunLoop应用篇--线程间通信

RunLoop应用篇–线程间通信

本文将承接上一章节,讲解关于RunLoop的应用问题,本文主要介绍线程通信的相关问题,说到线程通信,其实主要有两种方式:

1.performSelect On The Thread
2.Mach Port

performSelect On The Thread

框架为我们提供了强制在某个线程中执行方法的途径,如果两个非主线程的线程需要相互间通信,可以先将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在主线程执行的方法。

下面是提供的一些方法:

@interface NSObject (NSThreadPerformAdditions)

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
    // equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);

@end

其实,平常我们也会经常使用到这些方法,实际上就是线程之间的通信。

Mach Port

在苹果的Thread Programming Guide的Run Pool一节的Configuring a Port-Based Input Source 这一段中就有使用Mach Port进行线程间通信的例子。 其实质就是父线程创建一个NSMachPort对象,在创建子线程的时候以参数的方式将其传递给子线程,这样子线程中就可以向这个传过来的 NSMachPort对象发送消息,如果想让父线程也可以向子线程发消息的话,那么子线程可以先向父线程发个特殊的消息,传过来的是自己创建的另一个 NSMachPort对象,这样父线程便持有了子线程创建的port对象了,可以向这个子线程的port对象发送消息了。

当然各自的port对象需要设置delegate以及schdule到自己所在线程的RunLoop中,这样来了消息之后,处理port消息的delegate方法会被调用,你就可以自己处理消息了。

自己也尝试去实现主线程和子线程之间的通信,没有按照官方文档的实现方式,大致实现如下:

1.RunLoop add port

#pragma mark - add port
- (void)addPort
{
    if (self.port)
    {
        // This class handles incoming port messages.
        [self.port setDelegate:self];

        // Install the port as an input source on the current run loop.
        [[NSRunLoop currentRunLoop] addPort:self.port forMode:NSRunLoopCommonModes];
    }
}

首先,需要给主线程的runloop添加port,然后实现delegate。

2.开启子线程

#pragma mark - launchSecondThread
- (void)launchSecondThread{
    __weak AppDelegate *weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // Create the check-in message.
        NSPortMessage* messageObj = [[NSPortMessage alloc] initWithSendPort:weakSelf.port receivePort:weakSelf.port components:nil];

        if (messageObj)
        {
            // Finish configuring the message and send it immediately.
            [messageObj setMsgid:8];
            [messageObj sendBeforeDate:[NSDate date]];
        }
    });

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // Create the check-in message.
        NSPortMessage* messageObj = [[NSPortMessage alloc] initWithSendPort:weakSelf.port receivePort:weakSelf.port components:nil];

        if (messageObj)
        {
            // Finish configuring the message and send it immediately.
            [messageObj setMsgid:10];
            [messageObj sendBeforeDate:[NSDate date]];
        }
    });
}

此处,开启了两个子线程,主要使用NSPortMessage像同一个port发送消息,然后在port的delegate中处理消息,这里只是简单接受了线程的通信。

NSPortMessage好像只能在OS X上面使用,iOS平台上面不可用,代码示例也是在Mac平台上实现的。

这里,并没有完全按照官方文档的方式,感觉官方的文档更像是object之间的通信,具体可以参考官网的介绍。

总结

文中主要介绍了使用port进行线程之间的通信,介绍的比较简单,自己也写了一个demo,大家可以去我的github上查看。

参考:
Thread Programming Guide

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值