NSOperationQueue似乎performance缓慢
我是NSOperationQueue的新手,但是在当前的项目中,我需要一种取消asynchronous操作的方法。 我原来的代码使用GCD和工作。 这里是:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^{ rg = [[RiverGauge alloc] initWithStationInfo:[station id] forHistoryInHours:48 inThisFormat:nil]; dispatch_async(dispatch_get_main_queue(), ^{ [hud removeFromSuperview]; UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; GaugeViewController *vc = [sb instantiateViewControllerWithIdentifier:@"GaugeDetailViewController"]; [vc setRiverGauge:rg]; [self.navigationController pushViewController:vc animated:YES]; }); });
RiverGauge是一个可能需要很长时间的networking操作,特别是当用户在农村时。 我见过的大多数post都build议将其移入NSOperationQueue。 我做了如下:
NSOperationQueue *queue = [NSOperationQueue new]; NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(getGaugeDetail:) object:[station id]]; [queue addOperation:op];
在getGaugeDetail方法(在select器参数)中,我有以下代码:
RiverGauge *rg = [[RiverGauge alloc] initWithStationInfo:gaugeIdentifier forHistoryInHours:48 inThisFormat:nil]; UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; GaugeViewController *vc = [sb instantiateViewControllerWithIdentifier:@"GaugeDetailViewController"]; [vc setRiverGauge:rg]; [self.navigationController pushViewController:vc animated:YES];
使用GCD进行此操作时,它可通过快速的互联网连接快速响应。 但是,使用NSOperationQueue时,同样的操作需要几秒钟的时间。 返回的数据是准确的,但是。 再次,我对NSOperationQueue不是很熟悉。 有什么build议么?
谢谢!
在使用NSOperationQueue的代码中,看起来像是在NSOperationQueue中进行UI更改,这可能是在主线程以外的线程上执行的。 有时,当您与主线程中的UIKit元素进行交互时,它们要么不能正常工作,要么在显示结果出现之前有明显的延迟。 所以我的猜测是你看到了在错误的线程上进行UI更改的效果。
尝试在主线程上执行UIKit的东西,看看它是否似乎解决您的问题。 你可以继续使用GCD来做到这一点。
代替
[self.navigationController pushViewController:vc animated:YES];
你可以试试这个:
[self.navigationController performSelectorOnMainThread:@selector(someMethod) withObject:<#(id)#> waitUntilDone:NO]; -(void)someMethod { //pushViewController:animated: //and other stuffs }
另外如果你想取消操作,最好是使用NSOperation而不是NSOperation而不是NSInvocationOperation。 你可以创build一个NSOperation的子类,除了UI更新本身之外,你可以执行所有其他的东西。 它有一个属性“取消”。 你可以使用它和NSMutableURLRequest一起使用,如果你希望它被取消超时。
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
我不知道你在第二个线程中要做什么,除了主线程,但你必须记住的唯一的事情是,你必须将主线程从其他线程分开。 无论何时处理UI或更新UI,都必须在主线程中执行所有这些操作。 其余的操作和后台的东西可以由单独的线程通过使用NSOperationQueue来处理。 否则,您的UI可能会冻结。 请让我知道,如果它的工作。 谢谢 :) :)
首先,你不需要把它从GCD移到NSOperationQueue。 这没有意义。 问题是RiverGauge -initWithStationInfo:forHistoryInHours:inThisFormat:方法本身。
RiverGauge是一个可能需要很长时间的networking操作,特别是当用户在农村时。
如果你想取消这个方法,你必须执行一些方法来取消该方法,或者完全重写。 将networking操作从方法中分离出来,并使用asynchronousAPI(如NSURLConnection + sendAsynchronousRequest:queue:completionHandler:)是一个好主意。 您可以随时取消NSURLConnection。