2010-05-08 160 views
2

将数据从后台线程写入NSPasteboard对象是否安全?我似乎无法在任何地方找到明确的答案。我认为这个假设是数据将在拖动开始之前写入剪贴板。NSPasteboard是否线程安全?

背景:
我有一个从Evernote获取数据的应用程序。当应用程序第一次加载时,它获取每个音符的元数据,但不是音符内容。笔记存根然后列在大纲视图中。当用户开始拖动笔记时,笔记被传递到后台线程,后台线程处理从Evernote获取笔记内容。让主线程阻塞直到获得数据会导致显着的延迟和糟糕的用户体验,所以我有[outlineView:writeItems:toPasteboard:]函数返回YES,而后台线程处理数据并调用主线程将数据写入粘贴板对象。如果在用户将笔记放在某个地方之前笔记内容被传输,那么一切都很完美。如果用户在处理数据之前在某个地方放下笔记......那么,所有东西都会永久封锁。仅仅让后台线程将数据写入粘贴板是否安全?

回答

3

您可以将数据答应到剪贴板,而无需实际的数据呢。

一种方法是在粘贴板上声明数据的类型,将自己作为粘贴板的所有者传递,并通过提供数据(如果需要阻塞,直到数据到达或未到达)来响应a pasteboard:provideDataForType: message。这意味着您需要记住哪些对象被复制(例如,通过将它们存储在数组中),以便在承诺到期时从中提取/生成数据。

Harald Scheirich的回答中提到的另一种方法是让您的模型对象符合the NSPasteboardWriting protocol,理想情况下在一个类别中(将接口独立逻辑与Mac特定逻辑分开)。这比旧的方式要干净得多,但需要Mac OS X 10.6及更高版本。

使用NSPasteboardWriting,您可以通过让模型对象writingOptionsForType:pasteboard: method返回the NSPasteboardWritingPromised option来实现许诺。他们的pasteboardPropertyListForType: method将返回数据,或至少尝试 - 像以前一样,此方法应该阻塞,直到数据到达或未到达。

哦,并回答标题中的问题(“是NSPasteboard线程安全的吗?”):有一个在Thread Safety Summary没有明确的答案,但这个笼统的说法:

...可变对象一般不是线程安全的。要在线程应用程序中使用可变对象,应用程序必须进行适当的同步。

我会考虑NSPasteboard是一个可变对象,所以没有。

实际上,这不是问题:您通常只使用NSPasteboard来响应操作消息(例如,,copy:),拖动或服务调用,而这些都只发生在主线程上。对于他们发生在辅助线程上,您必须自己从辅助线程上运行的代码中明确发送这些消息,在这种情况下,您已经在做一些非常错误的事情。

+0

+1,优秀的答案。 – 2010-05-09 01:45:08

+0

谢谢!这个应用程序是针对10.5构建的,因此NSPasteboardWriting协议不存在。我会尝试一下粘贴板:provideDataForType:方法。我认为现在不会太困难。 – 2010-05-09 13:57:42

0

猜想:

我认为你的问题无关,与线程但事实证明,通过返回YES您告知数据已准备好系统。您是否曾尝试将您的数据移动到支持NSPasteboardWritingNSPasteboardReading的自定义类中?通过这种方式,数据访问者可以阻止数据准备就绪。

Pasteboard Documentation