2010-05-08 212 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