2

我遇到了这个奇怪的错误..基本上我得到了这个块定义:

UILabel* filterButtonLabel;
void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText, id delegate){
    filterButtonLabel.text = newLabelText;   // command A   
    dispatch_after(DISPATCH_SECONDS_FROM_NOW(1), dispatch_get_main_queue(), ^{
        [delegate abortFilter];  //command B
    });
};

这个块是从工作队列中调用的,如下所示:

dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(taskQ, ^{
    [searchWorker withDelegate:self withUpdater:labelUpdater]; //<- worker thread in here
});

updater(@"filter applied", delegate);

(我知道你会问:为什么要委托?别担心,它只是为我省去了很多麻烦,我相信这与这个讨论无关)。

我注意到的事情是command A这只在完成后执行command B..这个想法是用用户的一些信息更新 UI..然后在 1 秒后关闭持有该标签的 UI(我想给用户足够的时间阅读通知..知道发生了什么..然后让 UI 自行关闭)。

发生的事情是同时command A 执行和 UI 关闭!如果我将整个调度 after 子句取出..command A根据需要执行,就是这样。

我也试过这样做:

__block UILabel* filterButtonLabel;
void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText, id delegate){
    filterButtonLabel.text = newLabelText;   // command A   
    dispatch_after(DISPATCH_SECONDS_FROM_NOW(1), dispatch_get_main_queue(), ^{
        [delegate abortFilter];  //command B
    });
};

我也尝试将队列从更改dispatch_get_main_queue()dispatch_get_global_queue(),反之亦然..仍然没有运气..

想法?


更新(正确答案)

根据下面 Mohannad 的回答..这就是我的最终解决方案的样子(注意:事实证明,命令 A 和命令 B 都涉及 UI 更改。所以两者都应该在主队列中完成。有趣的部分是整个块被放置在一个全局队列中..这增加了他们的执行延迟,我也取出了委托,因为它没有必要)

void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText){
    dispatch_async(dispatch_get_main_queue(), ^ {
        filterButtonLabel.text = newLabelText;   // command A -> includes a UI change
    });
    
    dispatch_after(DISPATCH_SECONDS_FROM_NOW(2), dispatch_get_main_queue(), ^{
        [self abortFilter];  //command B -> also includes a UI change
    });
};
4

1 回答 1

2

UIKit 不是线程安全的。taskQ不是主队列,因此命令 A 将在全局队列而不是主队列上执行。

考虑将主队列分配给taskQ,或使命令 Adistpatch_async在主队列上执行。

于 2013-05-22T10:28:31.663 回答