2012-03-22 30 views
1

我发现这个线程作为参考:How do I wait for an asynchronously dispatched block to finish?和我正在使用该代码(发信号块内的信号量)等待我的线程完成测试之前完成。信号量从未在单元测试信号(dispatch_get_main_que()从来没有运行?)

但是我从来没有信号灯的信号,它的做...所以我通过代码加强,发现这个小片段中的代码永远不会运行:

 dispatch_async(dispatch_get_main_queue(), ^{ 
      [self removeDownloadSpinner]; 
      block(callback); 
     }); 

是否dispatch_get_main_queue()不是当我单位解雇测试?如果不是,你如何单元测试异步块?

编辑(这里是更多的代码): 基本上我有一个“ServerRequest”类,其中包含所有应用程序的传入/传出网络请求。一种方法是这样(完成块typedeffed):

+(void)checkPlayerCode:(NSString *)playerCode completionHandler:(PlayerCompletionBlock)block { 
    [self addDownloadSpinner]; 
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/players/%@",kBaseURL, playerCode]]; 
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; 
    [ServerConnectionRequest sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
    NSDictionary *p = [data objectFromJSONData]; 
    Player *player = [[Player alloc] init]; 
    player.last_name = [p objectForKey:@"last_name"]; 
    if (!error) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self removeDownloadSpinner]; 
      block(player); 
     }); 

    } 
}]; 

}

这是从一个UIViewController称为像这样:

[ServerRequest checkPlayerCode:codeCell.textField.text completionHandler:^(Player *p){ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"wooo block" message:@"works" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
    [alert show]; 
}]; 

然而dispatch_get_main_queue()块永远不会被解雇。

回答

1

的问题是,你正在等待信号灯的主线程,同时试图与dispatch_async主胎面执行一些代码(dispatch_get_main_queue( ),...)。 尝试使用NSRunLoop的runUntilDate,像

__block volatile bool loadComplete = false; 
dispatch_async(dispatch_get_main_queue(), ^(..) 
               {                  
                .. 
                loadComplete = true; 
               }); 

NSDate* startTime = [NSDate date]; 
while (!loadComplete) 
{ 
    NSDate* nextTry = [NSDate dateWithTimeIntervalSinceNow:0.1]; 
    [[NSRunLoop currentRunLoop] runUntilDate:nextTry]; 

    if ([nextTry timeIntervalSinceDate:startTime] > ../* some appropriate time interval here */) 
     STAssertTrue(false, @"TIMEOUT"); 
} 

// Assertions here 
1

在单元测试中执行多线程代码没有问题,我已经在其中运行了各种各样的调度代码。

当你说穿过代码时,你的意思是说你逐字地使用调试器。如果是这样,并且你认为代码没有运行,因为调试器没有停在块中,那么你必须记住这将在另一个线程上运行,并且你需要一个断点来停止它。

所以我会在块内分配断点。

其次,如果您测试的代码是从主线程运行,那么这将无法正常工作,因为您无法在您所在的同一线程上执行某些代码。单元测试代码应该在后台线程上运行。

然后是执行时间问题。因为你正在运行一个异步块,它可能只是它尚未执行。

异步调用的测试意味着上面的代码可能需要等待异步调用完成才能声明它可能已经完成的任何事情。在这种情况下,您必须考虑它应该是同步而不是异步。

你需要表现出更多的代码,我想:-)

+0

所以我在实际块更多的代码添加。是的,我的意思是我逐字逐句通过调试器。后台线程关闭......但回调块内部的中断不会被触发。也认为这个问题可能是测试在主线程上运行;然而,我只是试图在后台线程上运行测试(gcd priority default),它仍然无法正常工作。我是否应该发布我的测试? – Msencenb 2012-03-23 09:44:36

+0

想我越来越近了。问题在于我的信号量锁定了主线程,所以其他回调无法获得线程。但是,如果我将semaphore_wait调用移入异步线程,则单元测试不会等待并完成。任何机会你可以给我一个单元测试的例子,它使用信号量等待而不阻塞主线程? – Msencenb 2012-03-23 09:52:12

+0

对我没有任何帮助。几周前我做了一些信号量的代码,然后重构了它。但正如你所说,你必须小心锁定你正在执行的线程。正如我最近向其他人建议的那样,请看看GCD和运营。对于您正在尝试解决的较大问题,这可能是一个更容易,更好的答案。 – drekka 2012-03-23 13:41:59