如何暂停/继续NSThread

时间:2011-12-15 11:04:44

标签: objective-c cocoa

我有一个应用程序,我在其中使用函数FSMoveObjectToTrashSync。它适用于后台线程。我需要我的应用程序的能力,点击按钮暂停它或继续(如果它暂停)我怎么能做到这一点? 代码示例:

NSMutableArray *fileArray = [NSMutableArray array withobjects:@"file1url", @"file2", @"file3", nil]; 
NSMutableArray *threadArray = [[NSMutableArray alloc] init];

-(void)myFunc{
   for (NSURL *url in fileArray){
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mySelectorWith:) object:url];
        [thread start];
        [threadArray addObject:thread];
   }
}

-(void)mySelectorWith:(NSURL *) url{
       FSRef source;
       FSPathMakeRef((const UInt8 *)[[url path] fileSystemRepresentation], &source, NULL);
       FSMoveObjectToTrashSync(&source, NULL, kFSFileOperationDefaultOptions);
}

PS:对不起我的英语,我来自白俄罗斯...... =(

2 个答案:

答案 0 :(得分:2)

您可以使用NSConditionLock。 NSConditionLock类似于条件变量。它有几个基本方法,lockWhenCondition和unlockWithCondition,以及lock。一个典型的用法是让你的后台线程在条件锁上等待“lockWhenCondition:”,并在前台线程中设置条件,这会导致后台线程被唤醒。条件是一个简单的整数,通常是枚举。

以下是一个例子:

enum {
    kWorkTodo = 1,
    kNoWorkTodo = 0
}

- (id)init {
    if ((self = [super init])) {
        theConditionLock = [[NSConditionLock alloc] initWithCondition: kNoWorkTodo];
        workItems = [[NSMutableArray alloc] init];
    }
}

- (void)startDoingWork {
    [NSThread detachNewThreadSelector:@selector(doBackgroundWork) toTarget:self withObject:nil];
}

- (void)doBackgroundWork:(id)arg {
    while (YES) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSArray *items = nil;
        [theConditionLock lockWhenCondition:kWorkTodo]; // Wait until there is work to do
        items = [NSArray arrayWithArray:workItems]
        [workItems removeAllObjects];
        [theConditionLock unlockWithCondition:kNoWorkTodo];
        for(id item in items) {
            // Do some work on item.
        }
        [pool drain];
    }
}

- (void)notifyBackgroundThreadAboutNewWork {
    [theConditionLock lock];
    [workItems addObject:/* some unit of work */];
    [theConditionLock unlockWithCondition:kWorkTodo];
}

在这个例子中,当调用startDoingWork时,doBackgroundWork:将在后台线程上启动,但随后停止,因为没有任何工作要做。一旦调用了notifyBackgroundThreadAboutNewWork,那么doBackgroundWork:将启动并处理新工作,然后返回休眠状态等待新工作可用,这将在下次调用notifyBackgroundThreadAboutNewWork时发生。

答案 1 :(得分:2)

一种解决方案是用NSOperation子类替换单个线程上的for循环。每个操作都应该只丢弃一个对象;然后,为每个要删除的对象创建一个操作,并将所有操作放在NSOperationQueue上。

操作队列将在一个线程上运行每个操作,如果它看到足够的计算能力,它甚至可以在多个线程上运行多个操作。

An operation queue can be paused and resumed at will;当您暂停队列时,该队列中已经运行的任何操作都将完成,但在您恢复队列之前不会再启动。