如何停止在后台执行选择器? [英] how to stop performing selector in background?
问题描述
我有一个A类.在这个类中,我有一个方法,会调用[ self performSelectorInBackground:...]
.然后开始下载来自互联网的一些信息.
I have some class A. In this class i have a method,
which calls [self performSelectorInBackground:...]
. And it starts downloading
some info from internet.
当我点击主页"按钮,然后再次进入应用程序后,此后台方法将继续起作用.因此,如果我再次调用此方法,则我具有bad_access权限,因为后台方法已经在工作,并且我调用了两次.
After i tap Home button, then enter the app again, this background method keeps working. So, if i call this method again, i have bad_access, because background method is already working and i call it twice.
我可以在A类背景下停止执行选择器吗?例如在我的applicationDidEnterBackground吗?或者我可以检查选择器是否正在执行操作?
Can i stop performing selector in background of the class A? For example in my applicationDidEnterBackground? Or can i check, if selector is performing or something?
我发现了一些类似的东西
I found couple things like
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:a];
[NSObject cancelPreviousPerformRequestsWithTarget:a selector:@selector(startDownload) object:nil];
但是他们没有为我工作.所以
But they didn't work for me. So
我的objAppDelegate:
my objAppDelegate:
@inteface ObjAppDelegate
{
A *a;
}
@implementation ObjAppDelegate
{
-(void)applicationDidEnterBackground:(UIApplication *)application
{
//or it can be didBecomeActive..
//here. check if background task of class A is running, or just stop it ??
}
}
@implementation A
{
//some timer, or event, etc.
-(void)startDownload
{
[self performSelectorInBackground:@selector(runBackgroundTask) withObject:nil];
}
-(void)runBackgroundTask
{
//some network stuff..
}
}
我这样做是这样的:
threadForDownload = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain:) object:nil];
[threadForDownload start];
[self performSelector:@selector(startDownload) onThread:threadForDownload withObject:nil waitUntilDone:NO];
-
(void)threadMain:(id)data {NSAutoreleasePool * pool = [NSAutoreleasePool new];
(void)threadMain:(id)data { NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSRunLoop * runloop = [NSRunLoop currentRunLoop];[runloop addPort:[NSMachPort端口] forMode:NSDefaultRunLoopMode];
NSRunLoop *runloop = [NSRunLoop currentRunLoop]; [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
同时(是){[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];}
while (YES) { [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; }
[池释放];}
在我的startDownload方法中,我查看活动指示器以检查是否startDownload已经在运行..
In my startDownload method i look at activity indicator to check, whether startDownload is already running..
-(void)startDownload
{
if (![[UIApplication sharedApplication] isNetworkActivityIndicatorVisible]) // flag..
{
//....
}
}
//每次我开始下载时,我都会显示networkActivityIndicator
// I make visible networkActivityIndicator every time i start downloading
推荐答案
这是要做的事情:
- 后台任务使用 isCancelled 属性.
- 主线程发送
- the background task saves its thread to a property somewhere using NSThread currentThread
- the background task periodically checks the thread's isCancelled property.
- the main thread sends cancel to the thread object saved by the background thread in step 1.
- On exit, the background thread sets the property to nil.
用于存储线程的属性的所有操作都必须受 @synchronized
或同等保护,以防止主线程将 cancel
发送给已取消分配的对象线程对象.
All of the operations on the property used to store the thread in have to be protected by @synchronized
or equivalent to prevent the main thread from sending cancel
to a deallocated thread object.
后台线程不能执行阻塞时间超过一小段时间的IO操作.特别是,使用NSURLConnection的URL的同步下载已退出.如果使用NSURLConnection,则需要转到异步方法和运行循环(可以说,在这种情况下,您可以完全取消后台线程).如果您使用的是POSIX级别的IO,请在超时的情况下使用 poll()
.
The background thread can't do IO operations that block for more than a short period of time. In particular, synchronous downloading of URLs using NSURLConnection is out. If you are using NSURLConnection, you'll want to move to the asynchronous methods and a run loop (arguably, in that case, you can do away with the background thread altogether). If you are using POSIX level IO, use poll()
with a timeout.
这篇关于如何停止在后台执行选择器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!