【问题标题】:stopping a background execution before it gets executed在执行之前停止后台执行
【发布时间】:2012-03-10 09:09:46
【问题描述】:

我使用dispatch_async写了一个后台处理逻辑如下:

- (IBAction)textFieldChanged:(id)sender {
dispatch_async(kBgQueue, ^{
     NSArray *tempArray = [myClass getSuggestionArray]; //getSuggestionArray returns an array of objects from a database
        [self performSelectorOnMainThread:@selector(initSuggestionArray:) withObject:tempArray waitUntilDone:YES];
    });
}

如您所见,每次用户编辑文本字段时都会调用此方法(只要用户键入一个字母)。 kBgQueue 定义为:

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

我想要的是一些方法,一些逻辑,以便每当用户编辑该字段时,我可以检查此 kBgQueue 中是否已经有一个排队的任务,如果是,那么我想停止执行该排队的作业在开始下一个块之前。(想删除前一个块)我正在使用它,以便应用程序的 UI 看起来不像挂起,如果用户快速键入 3-4 个字符(因为结果来得太晚了我数据库)

【问题讨论】:

    标签: ios multithreading objective-c-blocks background-process


    【解决方案1】:

    您可以使用 NSOperationQueue 代替 GCD 队列并添加如下操作:

    [queue addOperationWithBlock:^{
        NSArray *tempArray = [myClass getSuggestionArray];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self initSuggestionArray:tempArray];
        });
    }];
    

    然后您可以取消所有操作

    [queue cancelAllOperations];
    

    如果您需要更细粒度的控制,您可以继承 NSOperation 并添加一些检查以查看操作是否已被取消。

    【讨论】:

    • 嘿,蒂姆,我认为操作没有被取消,因为每次都会调用 initSuggestionArrayMethod,取消操作后的事件。 gdb 显示日志为:void _WebThreadLockFromAnyThread(bool), 0x7a9cf60: 从主线程或 Web 线程以外的线程获取 Web 锁。不应从辅助线程调用 UIKit。
    • 您也可以使用 NSBlockOperation 并在调用 initSuggestionArray 之前检查是否已取消,您可以在此处找到示例:*.com/a/8113232/381870
    最近更新 更多