我有一些A班。在这堂课我有一个方法,
它调用[self performSelectorInBackground:...]
。它开始下载
来自互联网的一些信息。
点按“主页”按钮后,再次输入应用,此后台方法继续有效。 所以,如果我再次调用此方法,我有bad_access,因为后台方法已经工作,我调用了两次。
我可以停止在A级背景中执行选择器吗?例如在我的applicationDidEnterBackground中? 或者我可以检查,如果选择器正在执行或什么?
我发现了一些像
这样的东西[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:a];
[NSObject cancelPreviousPerformRequestsWithTarget:a selector:@selector(startDownload) object:nil];
但他们不适合我。 所以
我的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];
NSRunLoop *runloop = [NSRunLoop currentRunLoop]; [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (YES) { [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; }
[pool release]; }
在我的startDownload方法中,我查看活动指示器以检查是否 startDownload已经在运行..
-(void)startDownload
{
if (![[UIApplication sharedApplication] isNetworkActivityIndicatorVisible]) // flag..
{
//....
}
}
//每次开始下载时都会显示networkActivityIndicator
答案 0 :(得分:4)
您可以轻松创建BOOL
实例变量,以确定后台任务是否处于活动状态。
BOOL isBackgroundTaskRunning;
然后在runBackgroundTask
if (isBackgroundTaskRunning) {
// already running
return;
}
isBackgroundTaskRunning = TRUE;
...
isBackgroundTaskRunning = FALSE;
答案 1 :(得分:4)
以下是该做什么:
用于存储线程的属性上的所有操作都必须受@synchronized
或等效的保护,以防止主线程将cancel
发送到解除分配的线程对象。
后台线程无法执行阻塞超过一小段时间的IO操作。特别是,使用NSURLConnection同步下载URL已经完成。如果您正在使用NSURLConnection,那么您将需要转移到异步方法和运行循环(可以说,在这种情况下,您可以完全取消后台线程)。如果您使用的是POSIX级IO,请使用poll()
并超时。
答案 2 :(得分:1)
我不认为强制中断方法会省钱。您可以做的是更改对象的状态,并检查方法实现中的状态,以便在取消时提前返回(但不要忘记释放已分配的对象)。
这就是NSOperationQueue的工作原理。来自文档:
取消操作不会立即强制它停止正在进行的操作。虽然所有操作都需要遵守isCancelled返回的值,但是您的代码必须显式检查此方法返回的值并根据需要中止。
答案 3 :(得分:1)
在后台线程中运行该方法,并保留NSThread
的记录。然后,你可以结束线程。