2

如标题所述,我想UIManagedDocument同步打开,即我希望我的执行等到打开完成。我只在 mainThread 上打开文档。

当前打开的 API 使用块

[UIManagedDocument openWithCompletionHandler:(void (^)(BOOL success))];

链接中提到的锁使用在主线程以外的线程上运行良好。如果我使用 locks on mainThread,它会冻结应用程序的执行。

任何意见将是有益的。谢谢。

4

1 回答 1

2

首先,让我说我强烈反对这样做。您的主线程只是等待,在等待调用完成时什么也不做。在某些情况下,如果您的应用程序在主线程上没有响应,系统会终止您的应用程序。这是非常不寻常的。

我想您应该是决定何时/如何使用各种编程工具的人。

这正是你想要的......阻塞主线程,直到完成处理程序运行。同样,我建议这样做,但是,嘿,这是一种工具,我会采取 NRA 的立场:枪支不会杀人……

__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
    // Do your work in the completion handler block and when done...
    waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
    usleep(USEC_PER_SEC/10);
}

另一种选择是执行运行循环。然而,这并不是真正同步的,因为运行循环实际上会处理其他事件。我在一些单元测试中使用了这种技术。它与上面类似,但仍然允许在主线程上发生其他事情(例如,完成处理程序可能会调用主队列上的操作,这可能不会在前面的方法中执行)。

__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
    // Do your work in the completion handler block and when done...
    waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
    NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
    [[NSRunLoop currentRunLoop] runUntilDate:futureTime];
}

还有其他方法,但这些方法简单易懂,而且像拇指酸痛一样突出,所以很容易知道你在做一些非正统的事情。

我还应该注意,除了测试之外,我从未遇到过这样做的充分理由。您可以死锁您的代码,并且不从主运行循环返回是一个滑坡(即使您自己手动执行它 - 请注意,调用您的内容仍在等待并再次运行循环可能会重新输入该代码,或导致其他一些问题)。

异步 API 很棒。条件变量方法或对并发队列使用屏障是在使用其他线程时进行同步的合理方法。同步主线程与您应该做的相反。

祝你好运……并确保你登记你的枪支,并始终携带你的隐藏武器许可证。这当然是狂野的西部。总有一个约翰卫斯理哈登在那里寻找枪战。

于 2012-05-05T13:04:40.787 回答