线程和自动释放池问题 [英] Threads and autoreleasepool questions

查看:225
本文介绍了线程和自动释放池问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,有几种方法可以发送要在线程中执行的任务.我最常用的是:

As I understand there are several ways to send tasks to be performed in threads. The most common ones that I use are:

1)performSelector:withObject:afterDelay:

1) performSelector:withObject:afterDelay:

2)performSelectorOnMainThread:withObject:waitUntilDone:

2) performSelectorOnMainThread:withObject:waitUntilDone:

3)performSelectorInBackground:withObject:

3) performSelectorInBackground:withObject:

4)[NSThread detachNewThreadSelector:toTarget:withObject:]

4) [NSThread detachNewThreadSelector:toTarget:withObject:]

我的第一个问题是,除了明显的参数差异外,1)和2)之间有什么区别?它们实际上都在Main线程中工作吗(其自动释放池是在main.m中自动创建的)?我刚刚从某人在Stackoverflow上的帖子中了解到,方法1)实际上正在新线程中工作,因此应为其选择器方法创建一个自动释放池.这样对吗?我一直在使用1)很多东西,主要是为了利用delay参数,但是我从未为它们创建自动释放池.灾难性的事没有发生.

My first question is, what is the difference between 1) and 2), besides the obvious parameter differences? Are they actually both working in the Main thread (whose autorelease pool was automatically created in main.m)? I just read from someone's post on Stackoverflow that method 1) is actually working in a new thread, and so an autorelease pool should be created for its selector method. Is this correct? I've been using 1) a lot, mostly to take advantage of the delay parameter, but I've never created an autorelease pool for them. Nothing catastrophic has happened.

接下来,3)和4)都在单独的线程中执行任务.我听说在这些线程中绝对不应做过UI方面的工作,但我对严格意义上的UI感到困惑. 我正在尝试编写代码,以便在从Navigationcontroller模态启动tableview时基本上播放重复的加载动画.然后,动画在tableview控制器的viewDidLoad方法中停止.最初,我只是停留在启动模态视图的代码行上方的代码以启动动画.发生的事情是动画从未播放过.

Next, 3) and 4) both perform tasks in a separate thread. I hear that UI stuff should never be done in these threads, but I'm confused as to what is strictly UI. I was trying to write code to basically play a repeating loading animation while a tableview is launching modally from a navigationcontroller. The animation is then stopped in the viewDidLoad method of the tableview controller. Initially, I just stuck the code to start the animation above the lines of code that start the modal view. What happened was the animation was never played.

[[self loadingView] playAnimation];

SettingsViewController *menus = [[SettingsViewController alloc] initWithNibName:@"SettingsViewController" bundle:nil];

MyNavigationController *navController = [[MyNavigationController alloc] initWithRootViewController:menus];

[menus setParent:navController];
[navController setDelegate:self];
menus.mainViewController = self;

[self presentModalViewController:navController animated:YES];
[navController release];
[menus release];

然后我尝试了以下方法,它确实起作用了……

I then tried the following, and it worked...

[NSThread detachNewThreadSelector:@selector(settingsOpeningThread) toTarget:self withObject:nil];
[[self loadingView] playAnimation];



- (void) settingsOpeningThread {

NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];

SettingsViewController *menus = [[SettingsViewController alloc]   initWithNibName:@"SettingsViewController" bundle:nil];

MyNavigationController *navController = [[MyNavigationController alloc] initWithRootViewController:menus];

[menus setParent:navController];
[navController setDelegate:self];
menus.mainViewController = self;

[self presentModalViewController:navController animated:YES];
[navController release];
[menus release];

[apool release];

}

动画将一直播放,直到完全启动SettingsViewController视图为止.但是像这样启动模态视图是否算作"UI",应该避免吗?此外,每次启动模态视图时,我都会在Instruments中遇到一些奇怪的内存泄漏错误.但是它来自那些系统库"之一,我被告知很难调试.这里可能出什么问题了?

Animation keeps playing until the SettingsViewController view is fully launched. But does launching modal views like this count as "UI" and should be avoided? Also I am getting some weird memory leak errors in Instruments every time the modal view is launched. But it's from one of those "System Libraries", which I've been told is very difficult to debug. What might be going wrong here?

很抱歉为您提供如此冗长的帖子.任何帮助将不胜感激!

Sorry for the embarrassingly long post. Any help will be appreciated!

推荐答案

(1)为当前运行循环安排任务.在非常高的水平上,UIKit应用程序看起来像

(1) schedules a task for the current runloop. At a very high level, an UIKit application looks like

while(true) {
  update UI
  run all tasks that were scheduled last time through the loop
}

这就是为什么您没有在第一次尝试中看到UI更新的原因;对playAnimation的调用安排了UI在runloop的下一次迭代中进行更新,但是直到完成其后的代码后,UI才到达那里.

This is why you didn't see your UI updated in your first attempt; the call to playAnimation schedules the UI to be updated in the next iteration of the runloop, but it never gets there until the code that followed it is completed.

请注意,performSelector:withObject:afterDelay不会在单独的线程中运行指定的代码.

Note that performSelector:withObject:afterDelay does not run the specified code in a seperate thread.

(2)所做的事情非常相似,但是它没有为当前的运行循环调度某些东西,而是为主线程上的运行循环调度了一些东西.这仅在从单独的线程调用时才有用,通常是因为您要从辅助线程更新UI.

(2) does something very similar, but rather than scheduling something for the current runloop it schedules something for the runloop on the main thread. This is only useful if invoked from a separate thread, typically because you want to update the UI from a secondary thread.

是的,您的代码有点粗体.我建议做类似的事情:

And yes, your code is slightly bold. I would suggest to do something like:

[[self loadingView] playAnimation];
[self performSelector:@selector(loadTable) withObject:nil afterDelay:0]

其中要加载表的实际代码在loadTable中.这意味着当运行循环出现时,您的UI将被更新,动画开始播放,然后然后 loadTable方法被调用并完成其工作.

where the actual code to load the table is in loadTable. This means that when the runloop comes around, your UI will be updated, the animation starts playing, then the loadTable method gets called and do its job.

但是,如果动画需要来自主线程的干预才能执行,则此操作仍将不起作用.也就是说,如果加载表的代码使主线程停滞,则动画也可能停滞.除了在单独的线程中执行长期任务(它可能会或可能不会使用performSelector:onMainThread:waitUntilDone安排主线程上的UI更新)之外,实际上没有其他方法可以解决此问题.

This still will not work however if the animation requires intervention from the main thread to execute. That is, if the code to load the table stalls the main thread, your animation might stall too. There really is no way around that except doing the long run task in a separate thread (which may or may not use performSelector:onMainThread:waitUntilDone to schedule UI updates on the main thread).

如果您不太关心动画本身,则可能会找到类似 https://github之类的东西. com/samvermette/SVProgressHUD 有用.

If you don't care too much about the animation itself, you might find something like https://github.com/samvermette/SVProgressHUD useful.

这篇关于线程和自动释放池问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆