Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.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-Objective-C-如何停止NSThread,当它';她在等什么?_Ios_Objective C_Locking_Nsthread_Nscondition - Fatal编程技术网

iOS-Objective-C-如何停止NSThread,当它';她在等什么?

iOS-Objective-C-如何停止NSThread,当它';她在等什么?,ios,objective-c,locking,nsthread,nscondition,Ios,Objective C,Locking,Nsthread,Nscondition,我有一个nsthread,其中有一个while循环。它从main方法中的“线程安全”队列中获取对象。当我离开包含此nsthread对象的UIViewController时,我调用nsthread cancel方法,但它没有停止,因为它被“queueLock”NSCondition锁定。返回此UIViewController时,将创建一个新的nsthread并从队列中获取对象,但前一个线程仍然存在,并且两个线程都试图使用队列中的同一对象,这会导致内存管理问题。我的问题是,当我离开UIViewCon

我有一个nsthread,其中有一个while循环。它从main方法中的“线程安全”队列中获取对象。当我离开包含此nsthread对象的UIViewController时,我调用nsthread cancel方法,但它没有停止,因为它被“queueLock”NSCondition锁定。返回此UIViewController时,将创建一个新的nsthread并从队列中获取对象,但前一个线程仍然存在,并且两个线程都试图使用队列中的同一对象,这会导致内存管理问题。我的问题是,当我离开UIViewController时,应该如何停止此线程

NSThread主方法:

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while ([self isCancelled] == NO) {
    RenderRequest *renderRequest = [queue get];
    [self doRender:renderRequest];
    [renderRequest release];    
}

[pool drain];
这是队列类的get方法:

- (id) get {
    id toRet = nil;
    [queueLock lock];
    @try {
       while ([queueContents count] == 0) {
            [queueLock wait];
        }

        toRet = [queueContents lastObject];
        [queueContents removeLastObject];
    }

    @finally {
         [queueLock unlock];
         return toRet;
    }
}
谢谢

- (id) get
{
    id toRet = nil;
    [queueLock lock];
    @try
    {
        while ([queueContents count] == 0)
        {
            [queueLock wait];
            if ([self isCancelled]) return nil; // stop waiting
        }

        toRet = [queueContents lastObject];
        [queueContents removeLastObject];
    }
    @finally
    {
         [queueLock unlock];
         return toRet;
    }
}
主螺纹

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

while ([self isCancelled] == NO)
{
    RenderRequest *renderRequest = [queue get];
    if (renderRequest == nil) break; // should stop
    [self doRender:renderRequest];
    [renderRequest release];    
}

[pool drain];

然后您可以取消线程并通知queueLock停止等待

我编写了一个简单的演示,希望这能帮助您:)

demo.h

#import <Foundation/Foundation.h>

@interface test : NSObject
{
    NSCondition *queueCondition;
    NSThread *queueThread;

    NSMutableArray *queueTask;

    NSTimer *timer;
}
- (id)init;
@end

谢谢我尝试了这一点,但第二次打开UIViewController时,我在[pool drain]行收到了一个“[Not A Type release]:message sent to deallocated”错误,并且第一个线程仍然存在。我在UIViewController的ViewDidDemouse方法中调用了线程取消方法。谢谢,我将尝试一下。谢谢您的编写!我使用您编写的这个很好的演示来理解NSThread以及如何对数据进行排队。虽然现在每个人都指向GCD,但我认为记住NSThread的“手工完成”选项很重要。
#import "demo.h"

@interface demo (PrivateMethods)
- (void)threadTest;
- (void)cancelThread;
- (void)addTask;
@end


@implementation demo

- (id)init
{
    self = [super init];
    if (self) {
        if (!queueThread) {
            if (!queueCondition) {
                queueCondition = [[NSCondition alloc] init];
            }

            if (!queueTask) {
                queueTask = [[NSMutableArray alloc] initWithCapacity:5];
            }

            queueThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadTest) object:nil];
            [queueThread start];

            [self performSelector:@selector(cancelThread) withObject:nil afterDelay:10];

            if (!timer) {
                timer = [[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addTask) userInfo:nil repeats:YES] retain];
            }
        }
    }
    return self;
}

- (void)dealloc
{
    [queueThread release];
    [queueCondition release];
    [queueTask release];
    [timer invalidate];
    [timer release];
    [super dealloc];
}

- (void)threadTest
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    while (![[NSThread currentThread] isCancelled]) {
        [queueCondition lock];
        [queueCondition wait];

        if ([queueTask count] == 0) {
            [queueCondition unlock];
            continue;
        }

        NSString *str = nil;
        while ((str = [queueTask lastObject])) {
            NSLog(@"getTask: %@", [queueTask lastObject]);
            [queueTask removeLastObject];

        }

        [queueCondition unlock];
    }
    NSLog(@"threadTest end");
    [pool drain];
}

- (void)addTask
{
    [queueCondition lock];
    if (!queueTask) {
        queueTask = [[NSMutableArray alloc] initWithCapacity:5];
    }
    [queueTask addObject:@"new task"];
    [queueCondition signal];
    NSLog(@"add: new task");
    [queueCondition unlock];
}

- (void)cancelThread
{
    [timer invalidate];

    [queueThread cancel];

    [queueCondition lock];
    [queueCondition signal];
    [queueCondition unlock];
}
@end