线程间的通信

在一个进程中,线程往往不是孤立存在的,多个线程之间要经常进行通信,成为线程间的通信。

线程间的通信主要体现在,一个线程执行完特定任务后,转到另一个线程去执行任务,在转换任务的同时,将数据也传递给另外一个线程。

NSThread类提供了两个比较常用的方法,用于实现线程间的通信,这两个方法的定义格式如下:

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
在上述定义的格式中,第一个方法是将指定的方法放在主线程中运行。其中,aSelector就是在主线程中运行的方法,参数arg是当前执行方法所在的线程传递给主线程的参数,参数waitUntilDone是一个布尔值,用来指定当前线程是否阻塞,当为YES的时候会阻塞当前线程,直到主线程执行完毕后才执行当前线程;当为NO的时候,则不阻塞这个线程。
第二个方法是创建一个子线程,将指定的方法放在子线程中运行。

下面通过一个使用多线程下载网络图片的案例,展示如何实现线程间的通信:

1、新建一个Single View Application 应用,名称为03-ThreadContact;

2、进入Main.StoryBoard,从对象库拖拽一个ImageView到程序界面,用于显示要下载的图片,设置Mode模式为Center,最后给Image View设置一个背景颜色;

3、通过拖拽的方式,将ImageView在viewController.m文件的类扩展中进行属性的声明;

4、单击模拟器的屏幕,开始下载图片,并将下载完成的图片显示到ImageView上。

注意:程序如果直接在主线程中访问网络数据,由于网络速度的不稳定性,一旦网络传输速度较慢时,容易造成主线程的阻塞,从而导致应用程序失去响应。因此需要将网络下载图片这样耗时的操作放到子线程中,等下载完成后,通知主线程刷新视图,显示图片。

整个程序的代码如下:

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *HM;

@end

@implementation ViewController
// 单击屏幕
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self performSelectorInBackground:@selector(download) withObject:nil];
}
//下载图片
-(void)download
{
NSLog(@"download---%@",[NSThread currentThread]);
//1.图片地址
NSString *urlStr=@"https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1206121028,2489642848&fm=27&gp=0.jpg";
NSURL *url=[NSURL URLWithString:urlStr];
// 2.根据地址下载图片的二进制数据(这句代码最耗时)
NSData *data=[NSData dataWithContentsOfURL:url];
//3.设置图片
UIImage *image=[UIImage imageWithData:data];
//4.回到主线程,刷新UI界面(为了线程安全)
if(image!=nil)
{
[self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];
}
else
{
NSLog(@"图片下载出现错误!");
}
}
//下载完成
-(void)downloadFinished:(UIImage *)image
{
self.HM.image=image;
NSLog(@"downloadFinished---%@",[NSThread currentThread]);
}

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end
代码中,performSelectorInBackground: withObject:方法创建子线程,并指定了download方法来下载图片,后面调用

performSelectorOnMainThread: withObject: waitUntilDone:来到主线程,在主线程中刷新视图。

运行程序,程序运行成功后,单击屏幕,就成功下载了图片,模拟器的结果如下:
     

控制台输出结果如下:


---------------------
作者:ChunxueShi
来源:CSDN
原文:https://blog.csdn.net/shichunxue/article/details/78481428
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/striveLD/p/9930032.html