代码之家  ›  专栏  ›  技术社区  ›  RickiG

对于连续相互取消的小任务的突发性操作或线程?

  •  3
  • RickiG  · 技术社区  · 14 年前

    我想看看我是否可以针对一个Web服务进行一个“按你输入的搜索”的实现,它经过了足够的优化,可以在iPhone上运行。

    其想法是,用户开始在每个新字母后键入一个单词:“foo”,我等待xxx ms。要查看他们是否键入另一个字母,如果不键入,我将使用该单词作为参数调用Web服务。

    Web服务调用和对结果的后续分析,我希望移动到另一个线程。

    我编写了一个简单的SearchWebService类,它只有一个公共方法: - (void) searchFor:(NSString*) str;

    此方法测试搜索是否已在进行中(用户键入时延迟了xxx ms),然后停止该搜索并开始新的搜索。当结果准备就绪时,将调用委托方法:

    - (NSArray*) resultsReady;
    

    我不知道如何“线程化”这个功能。 如果每次一个用户有一个xxx毫秒的输入延迟,我都会不断地生成新的线程,结果我遇到了很多线程的问题,特别是因为我不需要任何其他搜索,只需要最后一个。 我尝试通过以下方式使一个线程始终在后台运行,而不是连续生成线程:

    - (void) keepRunning {
    
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        SearchWebService *searchObj = [[SearchWebService alloc] init];
        [[NSRunLoop currentRunLoop] run]; //keeps it alive  
        [searchObj release];
        [pool release];
    }
    

    但是我不知道如何访问“searchobj”对象中的“searchfor”方法,所以上面的代码可以工作并继续运行。我只是不能告诉你 searchObj 或检索 resultReady 物体?

    希望有人能给我指明正确的方向,穿线给我带来悲伤:) 谢谢您。

    1 回复  |  直到 14 年前
        1
  •  2
  •   RickiG    14 年前

    好吧,我花了8个小时来阅读外面的每一个例子。 我开始意识到,我必须做一些“概念验证”代码,看看是否在为“每一个”击键构建新的线程时会出现速度问题。

    结果表明,使用nsoperation和nsoperationqueue在速度方面,特别是在简单性和抽象性方面都是足够的。

    在每次按键后调用:

    - (void) searchFieldChanged:(UITextField*) textField {
    
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
        NSString *searchString = textField.text;
    
        if ([searchString length] > 0) {
    
            [self performSelector:@selector(doSearch:) withObject:textField.text afterDelay:0.8f];
        }
    }
    

    这主要是为了阻止代码表单开始搜索间隔小于800毫秒的击键。 (如果不是小触摸键盘的话,我会降低很多)。

    如果允许超时,则是搜索的时间。

    - (void) doSearch:(NSString*) searchString {
    
        [queue cancelAllOperations];
        ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
        [queue addOperation:searchOperation];
        [searchOperation release];
    }
    

    取消当前在队列中的所有操作。每次新搜索 开始时,它确保已经在进行的搜索操作按顺序关闭,还确保只有1个线程处于“未取消”状态。

    IssearchOperation的实现非常简单:

    @implementation ISSearchOperation
    
    - (void) dealloc {
    
        [searchTerm release];
        [JSONresult release];
        [parsedResult release];
        [super dealloc];
    }
    
    - (id) initWithSearchTerm:(NSString*) searchString {
    
        if (self = [super init]) {
    
            [self setSearchTerm:searchString];
        }
    
        return self;
    }
    
    - (void) main {
    
        if ([self isCancelled]) return;
        [self setJSONresult:/*do webservice call synchronously*/];
        if ([self isCancelled]) return; 
        [self setParsedResult:/*parse JSON result*/];
        if ([self isCancelled]) return;
    
        [self performSelectorOnMainThread:@selector(searchDataReady:) withObject:self.parsedResult waitUntilDone:YES];
    }
    
    @end
    

    有两个主要步骤:从Web服务下载数据和解析。 每次搜索后,我都会检查搜索是否被取消 [NSOperationQueue cancelAllOperations] 如果它有,那么我们返回并在dealloc方法中很好地清理了对象。

    我可能需要为Web服务和解析构建某种类型的超时,以防止队列在 起亚 对象。

    但现在这真的是闪电般的快,在我的测试中,我正在搜索一本16000条条目字典,并让xcode nslog将其记录到屏幕上(很好地减慢了速度),每800毫秒。我通过计时器发出一个新的搜索字符串,从而在旧的搜索字符串完成nslog结果到屏幕循环之前将其取消。 nsOperationQueue处理这一点时没有出现任何问题,而且执行的两个线程中不会超过几毫秒。UI完全不受在后台运行的上述任务的影响。