Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在main中,我生成一个新的NSThread,在main中的稍后某个点,当满足某个条件时,我希望停止该线程。怎样_Ios_Objective C_Multithreading_Concurrency_Nsthread - Fatal编程技术网

Ios 在main中,我生成一个新的NSThread,在main中的稍后某个点,当满足某个条件时,我希望停止该线程。怎样

Ios 在main中,我生成一个新的NSThread,在main中的稍后某个点,当满足某个条件时,我希望停止该线程。怎样,ios,objective-c,multithreading,concurrency,nsthread,Ios,Objective C,Multithreading,Concurrency,Nsthread,在命令行程序的主函数中,我创建了一个NSThread子类的新实例,并对其调用start,在不同的线程中运行计时器。如果用户想要停止计时器,他们输入stop,我希望它也结束线程 我该怎么做呢?我想我应该在线程上调用cancel,然后在NSThread子类的main中检查isCancelled是否为YES,但据我所知,main仅在我最初调用start时才被调用。我看不出还有什么地方可以检查isCancelled以调用[NSThread exit] 如何处理退出此NSThread?您可以在NSThre

在命令行程序的主函数中,我创建了一个NSThread子类的新实例,并对其调用start,在不同的线程中运行计时器。如果用户想要停止计时器,他们输入stop,我希望它也结束线程

我该怎么做呢?我想我应该在线程上调用cancel,然后在NSThread子类的main中检查isCancelled是否为YES,但据我所知,main仅在我最初调用start时才被调用。我看不出还有什么地方可以检查isCancelled以调用[NSThread exit]

如何处理退出此NSThread?

您可以在NSThread子类中检查isCancelled。您可以在NSThread子类的整个代码中检查isCancelled。调用cancel时,NSThread子类将继续运行,直到检查isCancelled。您要做的是将isCancelled支票放在希望的多个位置,当您调用cancel时,它会点击isCancelled支票并尽快退出

根据您发布的示例代码,我将TimerThread.m改为如下,效果良好:

#import "TimerThread.h"
#import "Giraffe.h"

@interface TimerThread () {
    Giraffe *giraffe;
}

@end

@implementation TimerThread

- (void)main {

    if (self.isCancelled)
        return;

    giraffe = [[Giraffe alloc] init];

    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(calculate:) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop] run];
}

- (void)calculate:(NSTimer*)timer {
    if (self.isCancelled) {

        [timer invalidate];

        return;
    }

    [giraffe calculateValues:timer];
}

@end
在NSThread子类中检查isCancelled。您可以在NSThread子类的整个代码中检查isCancelled。调用cancel时,NSThread子类将继续运行,直到检查isCancelled。您要做的是将isCancelled支票放在希望的多个位置,当您调用cancel时,它会点击isCancelled支票并尽快退出

根据您发布的示例代码,我将TimerThread.m改为如下,效果良好:

#import "TimerThread.h"
#import "Giraffe.h"

@interface TimerThread () {
    Giraffe *giraffe;
}

@end

@implementation TimerThread

- (void)main {

    if (self.isCancelled)
        return;

    giraffe = [[Giraffe alloc] init];

    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(calculate:) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop] run];
}

- (void)calculate:(NSTimer*)timer {
    if (self.isCancelled) {

        [timer invalidate];

        return;
    }

    [giraffe calculateValues:timer];
}

@end

根据各种注释,您可能需要以下主要方法:

+ (void) threadMain
{
    @autoreleasepool {
        [[NSThread currentThread] setName:@"WorkerThread.sharedThread"];
        NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        BOOL done = NO;
        while (!done) {
            @autoreleasepool {
                [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
                // check termination status:
                done = ...;
            }
        }
    }
}
一些解释:

[runLoop addPort:port]确保运行循环至少有一个事件源,否则,运行循环可能会过早返回

每次处理事件源后,运行循环都会返回。也就是说,您可以在事件发生后检查状态,例如,在模式等于NSDefaultRunLoopMode的运行循环上安排一个计时器

内部自动释放池是必需的,因为[NSDate distantFuture]返回一个自动释放对象-除非您拥有该自动释放池,否则这可能会堆积起来

必须根据在此线程上执行的代码设置变量done-否则,您需要内存屏障或其他同步原语,以确保在不同线程上所做的更改在此线程中可见


根据各种注释,您可能需要以下主要方法:

+ (void) threadMain
{
    @autoreleasepool {
        [[NSThread currentThread] setName:@"WorkerThread.sharedThread"];
        NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        BOOL done = NO;
        while (!done) {
            @autoreleasepool {
                [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
                // check termination status:
                done = ...;
            }
        }
    }
}
一些解释:

[runLoop addPort:port]确保运行循环至少有一个事件源,否则,运行循环可能会过早返回

每次处理事件源后,运行循环都会返回。也就是说,您可以在事件发生后检查状态,例如,在模式等于NSDefaultRunLoopMode的运行循环上安排一个计时器

内部自动释放池是必需的,因为[NSDate distantFuture]返回一个自动释放对象-除非您拥有该自动释放池,否则这可能会堆积起来

必须根据在此线程上执行的代码设置变量done-否则,您需要内存屏障或其他同步原语,以确保在不同线程上所做的更改在此线程中可见


但是我的NSThread子类只被调用一次,而且据我所知,它只执行一次。一旦它的主函数完成,NSThread就会退出。一旦它完成了,你就不必显式地调用cancel。你能发布代码吗?你的意思是在main方法之外还有其他方法要签入isCancelled吗?下面是一个示例项目,我正在描述这种情况:基本上,我在NSThread子类上调用start,它运行一个计时器。稍晚一点,但在主函数返回之前,我想停止线程,因为不再需要计时器。不过,我与子类交互的唯一时间是启动它,因此我看不出我将在何处放入稍后调用的检查。@DougSmith如果使用计时器,还需要运行循环。运行循环也需要返回,以便您可以从main返回。但是我的NSThread子类只被调用一次,据我所知,只执行一次。NSThread将在其主函数完成后退出。一旦它完成了,你就不必显式地调用cancel。你能发布代码吗?你的意思是在main方法之外还有其他方法要签入isCancelled吗?下面是一个示例项目,我正在描述这种情况:基本上,我在NSThread子类上调用start,它运行一个计时器。稍晚一点,但在主函数返回之前,我想停止线程,因为不再需要计时器。不过,我与子类交互的唯一时间是启动它,所以我看不到
我将支票放在什么地方,稍后会调用。@DougSmith如果你使用计时器,你还需要一个运行循环。运行循环也需要返回,这样您就可以从main返回。NSThread在主函数返回后终止。@CouchDeveloper我希望它在此之前终止。您必须提前从main返回的唯一选项由@random Ready非常准确地描述。NSThread在主函数返回后终止。@CouchDeveloper我希望它在此之前终止那就是,@random ready.+1说得很好的@CouchDeveloper这实际上帮助我调整了一个现有的项目:P@random出于好奇:你能解决什么问题?我一直在研究将大量数据解析为CoreData的最佳方法,并获得了一些经验NSOperation子类共享工作负载。我使用的解决方案与我向他提供的类似,但您发布的内容让我找到了另一种可能更干净的解决方案+1说得好@CouchDeveloper这实际上帮助我调整了一个现有的项目:P@random出于好奇:您能解决什么问题?我一直在研究将大量数据解析为CoreData的最佳方法,并让一些NSOperation子类共享工作负载。我使用的解决方案与我向他提供的类似,但您发布的内容让我找到了另一种可能更干净的解决方案