7

以前のバージョンの MonoTouch では、監視されていない例外を無視するためにこれを行っていました。

TaskScheduler.UnobservedTaskException += delegate(object sender, UnobservedTaskExceptionEventArgs e) {
    Console.WriteLine (e);
    e.SetObserved ();
};

それが良い習慣であるかどうかは議論の余地がありますが、 Xamarin.iOS 6.4 で正式にサポートされるasyncようになった/awaitキーワードで同じ効果を達成する方法を知りたいです。

テストに使用するコードは次のとおりです。

async void OnClick (object sender, EventArgs e)
{
    await Task.Run (() => { throw new Exception (); });
}

実行すると、デバッガーが一時停止しAsyncVoidMethodBuilderます:

ここに画像の説明を入力

.NET 4.5では動作が変更されたため、監視されていない例外によってアプリがクラッシュしないようになっていると読みましたが、例外が処理できない UIKit 同期コンテキストにポストされた場合、これは役に立ちません。

awaitMonoTouch で監視されていない例外を無視する方法はありますか?

4

1 に答える 1

7

async voidこれはメソッドの正しい動作です。メソッドは、メソッドの開始時にアクティブだった で例外を発生させることになっています。SynchronizationContextasync void

.NET 4.5 で言及した変更は、監視されていないタスクの例外のみを処理するものであり、async voidメソッドには適用されません。

(Microsoft) .NET の世界では、SynchronizationContext実装が異なればトップレベルのエラー処理も異なります。WPF、WinForms、および ASP.NET にはすべて、通常はApplication型の一部として、そのエラーを処理するさまざまな方法があります。

私は通常の Mono ユーザーではありませんが、Mono の UIKit API を調べましたが、トップレベルのエラー処理が見つからず、UIApplication公開UIKitSynchronizationContextされていないようです (または少なくとも文書化されていません)。

この問題の別の見方: メソッドの例外処理動作は、イベント ハンドラーasync voidと同じように設計されています (詳細については、MSDN の記事を参照してください)。したがって、別の質問で質問に答えることができます: UIKit では、この例外をどのように処理しますか?

void OnClick (object sender, EventArgs e)
{
  throw new Exception();
}

async voidまったく同じ方法で例外を処理します。

または、 を使用し続けたい場合UnobservedTaskExceptionは、単にタスク例外を観察できません (async voidコードでTask.Runは、例外を取得するタスクを返し、 を使用してそれを観察していますawait)。

void OnClick (object sender, EventArgs e)
{
  Task.Run(() => { throw new Exception(); });
}

ただし、async voidfor イベント ハンドラーを使用し、(最終的には)awaitすべてのタスクを ing することをお勧めします。これにより、プログラムが正常に動作しなくなり、その理由がわからないという「サイレント エラー」(無視されたタスク例外) が発生しないことが保証されます。

于 2013-07-25T12:59:00.690 に答える