3

UIView.StringSizeのような非同期コード内から実行すると、そのメソッドはto (MonoDevelopの「Gotodeclaration」。ライセンスでここに投稿できるかどうかわかりません)の呼び出しで始まるため、Task.ContinueWith爆発します。UIKitThreadAccessExceptionUIApplication.EnsureUIThread

Task.Factory.StartNew(() => {
    // Blows up discretely...nothing written to application output.
    // Also blows up for UIViews that exist only in code (not rendered).
    SizeF textSize = someView.StringSize(someString, someFont, new SizeF(someView.Bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
    Console.WriteLine(textSize);
});

この簡略化されたバージョンをでラップするとInvokeOnMainThread、すべてがうまくいきますが、その呼び出しなしでテキストを測定したい場合があります。同様に、私は例外の目的を完全に理解しており、以前に非同期コードの奥深くで何かを呼び出したときに多くの手間を省きましたが、この場合、EnsureUIThreadここでの使用は不要のようです。その呼び出しをNSStringクラスのヒットとして単純に言い換えると、UIスレッドの外で問題なく実行されます。

Task.Factory.StartNew(() => {
    // Outputs expected size data: "{Width=##, Height=##}".
    using (NSString nssSomeString = new NSString(someString)) {
        SizeF textSize = nssSomeString.StringSize(someFont, new SizeF(someView.Bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
        Console.WriteLine(textSize);
    }
});

のコードUIView.StringSizeはほぼ同じNSString作業を行うようであり、UIスレッド指向の露骨なものは何もないようです。このバージョンのメソッドをUIスレッドから呼び出す必要がある何かが欠けていますか?

編集(2013-01-17):

Xamarinにバグを報告して、彼らの応答を確認しました。このメソッドをとしてマークすることを検討しているようThreadSafeです。

4

2 に答える 2

1

これは、UIView作成されていないスレッドからアクセスしているためです。NSStringバックグラウンドスレッドで作成しているため、2番目の例は正常に機能し、推奨されます。someView.Bounds(バックグラウンドスレッドからアクセスすることも試みるべきではないと思いますが)

これもうまくいくと思います:

var bounds = someView.Bounds; //UI thread
Task.Factory.StartNew(() => {
    // Outputs expected size data: "{Width=##, Height=##}".
    using (UIView view = new UIView()) {
        SizeF textSize = view.StringSize(someString, someFont, new SizeF(bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
        Console.WriteLine(textSize);
    }
});

しかし、私は固執するでしょうNSString

var bounds = someView.Bounds; //UI thread
Task.Factory.StartNew(() => {
    // Outputs expected size data: "{Width=##, Height=##}".
    using (NSString nssSomeString = new NSString(someString)) {
        SizeF textSize = nssSomeString.StringSize(someFont, new SizeF(bounds.Width, float.MaxValue), UILineBreakMode.WordWrap);
        Console.WriteLine(textSize);
    }
});
于 2013-01-17T18:50:40.727 に答える
0

メソッドのUI制限StringSizeは実際には不要です。Xamarinは、これを「v6.0.10+」ですでに修正しています。

DrawString(drawInRect:*セレクター)が他のスレッドから問題ないことはすでに確認済みです。StringSizeはその機能のサブセットであるため、安全である必要があります。将来のバージョン(6.0.10以降)は[ThreadSafe]としてマークされます。

更新されたバージョンに対してコーディングするまで、NSStringバージョンは問題なく機能します。

于 2013-01-22T17:20:59.237 に答える