【问题标题】:Asynchronous dispatch in a called method被调用方法中的异步调度
【发布时间】:2013-05-04 21:00:31
【问题描述】:

我正在尝试使用确定的进度条完成长时间计算。这适用于以下代码。但是,在调用scan 的方法中,它会在scan 完成更新StoredLibrary 对象之前立即转到scoreWithEquation。我已经尝试了所有不同的方法来等待调度队列完成,但它们最终都会挂起 UI。我需要使用回调吗?我已经研究过这个解决方案,但我不明白如何来回传递所有参数和返回变量。

-(void) scan{
if (!_sheet){
    [NSBundle loadNibNamed: @"ProgressSheet" owner: self];
}
[NSApp beginSheet: _sheet
   modalForWindow: [[NSApp delegate]window]
    modalDelegate: self
   didEndSelector: NULL
      contextInfo: nil];

[_sheet makeKeyAndOrderFront:self];

[_progressBar setIndeterminate:YES];
[_progressBar setMinValue:0];
[_progressBar startAnimation:self];

__block NSMutableArray *tempTracks = [[NSMutableArray alloc]init];

//do stuff

dispatch_async(dispatch_get_global_queue(0, 0), ^{

        //do stuff
        [_progressBar setDoubleValue:0.f];
        [_progressBar setMaxValue:[listTracks count]];
        [_progressBar setIndeterminate:NO];

        for (iTunesTrack *listTrack in listTracks) {
            //do stuff to tempTracks
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                [_progressBar incrementBy:1];
            }); 
        }
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        [_progressBar setIndeterminate:YES];
        [NSApp endSheet:self.sheet];
        [self.sheet orderOut:self];
        self.listTracks = tempTracks;
    });
});
}

下面是调用scan的代码:

- (IBAction)evaluate:(id)sender {
        if (self.storedLibrary == nil){
            self.storedLibrary = [[StoredLibrary alloc] init];
            [self.storedLibrary scan];
        }
self.tableTracks = [self.storedLibrary scoreWithequation:[_scoringEquation stringValue]
                                               sortOrder:[_sortOrder titleOfSelectedItem]                                                                                                   
                                              trackLimit:[_trackLimit integerValue]];
}

我想将scanscoreWithEquation 保留为单独的方法,因为它们在其他地方被单独调用。

【问题讨论】:

    标签: objective-c macos cocoa cocoa-sheet


    【解决方案1】:

    当你使用dispatch_async时,调度的block不会阻塞当前线程,会立即继续执行。

    在您的情况下,当您调用 scan 时,您会做一些事情,然后调用 dispatch_async 来做其他事情。调度块中的所有内容都不会在此运行循环中执行,并且 [self.storedLibrary scan] 返回,因此 scoreWithequation 将立即执行。

    如果你想阻塞当前线程(执行dispatch调用的线程)你需要使用dispatch_sync。

    如果你想在scan之后执行scoreWithequation,你可以创建一个serial_queue,dispatch_async同时scan和scoreWithequation到自定义的serial_queue。这样做不会阻塞当前线程,它们会被连续执行。

    检查“创建串行调度队列”(http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

    或者保留一个完成块来执行 scoreWithequation 作为回调也是一种可能。

    【讨论】:

    • 我实际上已经尝试过了,但它不起作用。 scan 正在更新的实例变量 (listTracks) 在调用 scoreWithEquation 时似乎没有更新。我在想这可能是因为调度是在实例变量更新之前发送的。
    • 在你的代码中 scoreWithEquation 在 scan 执行“//do stuff to tempTracks”之前被调用。如果您分派到串行队列,它们将按顺序执行。您必须将异步 scoreWithequation 分派到“扫描”的同一串行队列
    • 我刚刚又试了一次,发现问题出在哪里。将self.listTracks = tempTracks; 移到`dispatch_async(dispatch_get_main_queue()` 块之外似乎是问题所在。如果它在里面,则在调用scoreWithEquation 后更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 2020-01-17
    • 1970-01-01
    相关资源
    最近更新 更多