假设您有一个对象在私有调度队列内部执行某些操作(请考虑那些不熟悉GCD的线程)。该对象在整个工作的不同时间通知其代表。从代码当前运行的私有队列调用委托方法是一个坏主意,还是应该在更知名的队列上调用它们?如果是后者,什么队列?似乎主队列可能并不总是你想要的。
选项A
dispatch_async(private_queue, ^{
// Do some work...
[self.delegate tellItWorkWasDone:self];
});
选项B
dispatch_async(private_queue, ^{
// Do some work...
dispatch_sync(dispatch_get_main_queue(), ^{
[self.delegate tellItWorkWasDone:self];
});
});
选项A的好处在于它的简单,但缺点是实现委托方法的人将在队列上运行代码,而这些代码实际上不应该在其上。选项B可能更安全,但main_queue只是一个例子;两个人应该如何确定应该使用哪个队列?
由于
答案 0 :(得分:2)
我建议使用一个选项C,实际上:为委托回调设置一个专用队列,除非必须在你的课程继续之前完成委托的活动,在这种情况下使用选项A.
如果UI需要更新,委托可以调度到主队列本身,不要强制它在上面。
答案 1 :(得分:1)
如果您的代表负责更新用户界面,那么您绝对应该使用选项B,因为Apple says
重要:并非所有UIKit类都是线程安全的。在对应用程序主线程以外的线程执行与绘图相关的操作之前,请务必查看文档。
如果不是这种情况,选项A也应该没问题。
答案 2 :(得分:1)
我认为这是您和API用户之间的合同问题。无论您选择哪种方法,都要明确它,因为您的API用户必须知道它。
正如@andreagiavatto正确指出的那样,决定的重要性在于必须在主线程上完成更新UI。如果您尚未明确说明回调或完成处理程序是否始终在主线程上排队,则API的用户必须始终采取额外步骤将其包装在另一个主线程中dispatch_async()到主线程,如果它与UI相关。
如果您是API的唯一用户,那么明确且保持一致有助于避免愚蠢的错误。
以下是我选择的方式:
答案 3 :(得分:1)
您还可以向您的类的init添加delegateQueue参数。这样,您就可以让类的使用者完全控制在哪个队列上触发委托调用。
其他答案是正确的,说UI操作应该在主队列上进行。如果您的类将代理调用在主队列上排队,而消费类不需要它,那将是一种浪费。