1

私のUIKitDisposeオーバーライドのほとんどは、他のビューが破壊される前に、他のビューで何かを行います。

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ファイナライザースレッドで実行されることに気づきました。 この場合、不正な非UIスレッドから呼び出されます。disposingfalse
ScrollView.RemoveObserver

UIKit関連のクリーンアップを安全に行う方法は何Disposeですか?

4

3 に答える 3

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内にアタッチ/デタッチする方がよい場合があります。そうすれば、この問題を完全に回避できます。

于 2013-02-05T17:12:02.787 に答える
4

Adam Kempは、Xamarinフォーラムのミラースレッドにすばらしい説明を投稿しました。

その場合にのみ、その作業のいずれかを実行する必要がありますdisposingtrueその場合 false、ファイナライザーから呼び出されているため、他のオブジェクトにアクセスするのは安全ではありません。その場合にアクセスする必要があるのは、管理されていないリソース(IntPtr解放する必要のあるネイティブ割り当てや強制終了する必要のあるネイティブスレッドなど)だけです。

これは明らかに、あなたが現在そこで行っている仕事をいつ行うべきかという問題を提起します。ビューコントローラを使用している場合は、のようなメソッドを使用できますWillDisappear。ビューにいる場合は、使用することができますWillMoveToWindow(ウィンドウから削除されている場合は、ウィンドウとしてnullで呼び出されます)。

に関するもう1つの重要なビットReleaseDesignerOutlets

ファイナライザーから呼び出された場合も呼び出すことはできませんReleaseDesignerOutlets。ファイナライザーでオブジェクトによって参照されている他の管理対象オブジェクトを確認することは安全ではないことを忘れないでください。それらのオブジェクトはもう存在しない可能性があります。

これらの他の各オブジェクトにはすでに同様のファイナライザーがあるため、これはスキップしても安全です。あなたがDispose()彼らを呼ぶことに慣れていない場合、彼らはファイナライザースレッドから彼らのファイナライザーを呼び出します、そしてその場合、彼ら自身のファイナライザーは Dispose(bool)falseで彼ら自身を呼び出します、それは「あなたはファイナライザーから呼び出されている」ことを意味します。ネイティブオブジェクトはアンマネージリソース(単なる )であるため、それらのメソッドがそれらのネイティブリソースへの参照を解放して、それらのネイティブオブジェクトがメモリを離れることができるようにするのIntPtrは安全です。Dispose(bool)

実際にアセンブリブラウザを使用して、私が今説明したことを確認するためにとメソッドNSObjectが 何をするかを調べることができます。何をするにしても、ファイナライザー内から管理対象リソースにアクセスしないでください。つまり、破棄引数がfalseの場合から管理対象リソースにアクセスしないでください。FinalizeDispose(bool)Dispose(bool)

ありがとうアダム!

于 2013-02-06T06:44:43.580 に答える
0

使用してもらえますか

InvokeOnMainThread(delegate {....})

UIKitのものを殺すために?100%確実にあなたが望むことをするわけではありませんが、それはあなたが別のスレッドにいる/いるときにUIKitのことをする通常の方法です。

于 2013-02-06T12:02:55.110 に答える