从后台线程向NSPasteboard对象写入数据是否安全?我似乎在任何地方都找不到明确的答案。我认为假设数据将在拖动开始之前写入粘贴板。
背景:
我有一个从Evernote获取数据的应用程序。当应用程序第一次加载时,它获取每个笔记的元数据,但不获取笔记内容。然后在大纲视图中列出注释存根。当用户开始拖动笔记时,笔记将被传递到后台线程,该线程负责从Evernote获取笔记内容。让主线程阻塞直到获得数据会导致显著的延迟和糟糕的用户体验,因此我让[outlineView:writeItems:toPasteboard:]
函数在后台线程处理数据并调用主线程将数据写入粘贴板对象时返回YES
。如果笔记内容在用户将笔记放到某个位置之前被传输,则一切工作正常。如果用户在处理数据之前将笔记放在某个地方...好吧,所有的东西都会永远阻塞。仅仅让后台线程将数据写入粘贴板是否安全?
发布于 2010-05-09 01:06:50
您可以将数据承诺到粘贴板,而不需要实际拥有数据。
一种方法是在粘贴板上声明数据的类型,将您自己作为粘贴板的所有者,并通过提供数据来响应a pasteboard:provideDataForType:
message (如果需要,阻塞,直到数据到达或未能到达)。这意味着您需要记住复制了哪些对象(例如,通过将它们存储在数组中),以便在承诺到期时可以从中提取/生成数据。
Harald Scheirich的答案中提到的另一种方法是使您的模型对象符合the NSPasteboardWriting protocol,理想情况下是在一个类别中(将接口独立逻辑与Mac特定逻辑分开)。这比以前的方法干净得多,但需要MacOSX10.6和更高版本。
使用NSPasteboardWriting,您将通过让模型对象的writingOptionsForType:pasteboard:
method返回the NSPasteboardWritingPromised
option来实现promises。他们的 pasteboardPropertyListForType:
method将返回数据,或者至少尝试-像以前一样,这个方法应该阻塞,直到数据到达或无法到达。
哦,为了回答标题中的问题(“NSPasteboard线程安全吗?”):Thread Safety Summary中没有具体的答案,但有这样的通用声明:
…可变对象通常不是线程安全的。要在线程化应用程序中使用可变对象,应用程序必须进行适当的同步。
我认为NSPasteboard是一个可变对象,所以不是。
在实践中,这不是问题:您通常只在响应操作消息(例如,copy:
)、拖动或服务调用时才使用NSPasteboard,而且这些操作都只发生在主线程上。为了让它们发生在辅助线程上,您必须自己显式地从在辅助线程上运行的代码中发送此类消息,在这种情况下,您已经在做一些非常错误的事情了。
发布于 2010-05-08 23:08:14
猜想:
我认为您的问题与线程无关,而是通过返回YES
告诉系统数据已准备好的事实。您是否尝试过将数据移动到支持NSPasteboardWriting
和NSPasteboardReading
的自定义类中?这样,数据访问者就可以阻塞数据,直到数据准备就绪。
https://stackoverflow.com/questions/2795798
复制相似问题