2013-02-05 23 views
1

我的UIKit Dispose覆蓋的大部分不與其他意見的東西,他們被摧毀之前:如果我無法從其他線程調用UIKit,我該如何清理Dispose?

protected override void Dispose (bool disposing) 
{ 
    if (ScrollView != null) { 
     ScrollView.RemoveObserver (this, new NSString ("contentOffset")); 
     ScrollView.RemoveObserver (this, new NSString ("contentInset")); 
     ScrollView = null; 
    } 

    base.Dispose (disposing); 
} 

我剛剛意識到Dispose將在終結器線程運行,如果disposingfalse
在這種情況下,ScrollView.RemoveObserver將從非UI線程調用,該線程爲Bad。

什麼是安全的方式做的UIKit相關的清理在Dispose

+0

只是檢查 - 如果處置是真的'會在終結器線程上運行'應該讀爲'假'? – Stuart

+0

@Stuart Yup,謝謝。 –

回答

4

如果處置是false,那麼你很可能是最好不要調用該代碼。

protected override void Dispose (bool disposing) 
{ 
    if (disposing) 
    { 
     if (ScrollView != null) { 
      ScrollView.RemoveObserver (this, new NSString ("contentOffset")); 
      ScrollView.RemoveObserver (this, new NSString ("contentInset")); 
      ScrollView = null; 
     } 
    } 
    base.Dispose (disposing); 
} 

作爲一個更普遍的回答你的問題 - 假設這個代碼是在一個UIViewController - 這可能是更好的安裝/拆卸內部ViewDidAppear,ViewDidDisappear這些觀察家 - 那麼你就可以完全避免這個問題。

+0

感謝您的回答。這是在一個自定義視圖內,我假設我可以將它移動到'RemoveFromSuperview'。 –

4

亞當·肯普張貼在mirror thread on Xamarin forums很好的解釋。

只有disposingtrue你應該做的任何工作。如果它是 false那麼你是從一個終結器被調用,所以它不是安全 訪問該其他對象。在這種情況下你應該訪問的唯一東西是任何非託管資源(例如IntPtr,它存儲你需要釋放的本地分配的 或你需要的本地線程)。

這顯然帶來了的時候做你 目前在那裏做什麼工作的問題。如果你在視圖控制器中,那麼你可以使用WillDisappear這樣的方法來使用 。如果你是在一個視圖中,那麼你可以 只使用WillMoveToWindow(它被調用,使用null作爲窗口 如果你正在從窗口中刪除)。

Another important bit關於ReleaseDesignerOutlets

從一個終結 稱爲既可以當你不能叫ReleaseDesignerOutlets。請記住,查看您的終結器中的對象所引用的任何其他管理對象 並不安全。這些對象可能不存在更長的 。

這是安全的跳過,因爲每個與其他物體已經有 類似的終結。如果你從不打電話Dispose() 他們然後他們將從終結者 線程調用他們的終結器,在這種情況下,他們自己的終結器將調用他們自己的 Dispose(bool)與虛假,這意味着「你被稱爲從一個 終結者「。由於本地對象是非託管資源(僅爲 IntPtr),因此它們的Dispose(bool)方法可以安全地釋放對這些本機資源的引用 以允許這些本機對象保留內存。

您可以實際使用的組件瀏覽器看看NSObjectFinalizeDispose(bool)方法做驗證什麼,我只是描述。 無論您做什麼,都不要從 終結器中訪問您的受管資源,這意味着如果 處置參數爲false,則永遠不會從Dispose(bool)訪問它們。

謝謝亞當!

0

你能使用

InvokeOnMainThread(delegate {....}) 

殺UIKit的東西嗎?不是100%確定它會做你想做的事,但那是做UIKit的東西,當你可能在/不在一個線程上。

+0

雖然我不確定它是否安全。 –

相關問題