9

この例は「失敗」します。

static async void Main(string[] args)
{
    try
    {
        await TaskEx.Run(() => { throw new Exception("failure"); });
    }
    catch (Exception)
    {
        throw new Exception("success");
    }
}

つまり、「失敗」というテキストを含む例外が発生します。

次に、この回避策を試しました:

static async void Main(string[] args)
{
    try
    {
        await SafeRun(() => { throw new Exception("failure"); });
    }
    catch (Exception)
    {
        throw new Exception("success");
    }
}

static async Task SafeRun(Action action)
{
    var ex = default(Exception);
    await TaskEx.Run(() =>
    {
        try
        {
            action();
        }
        catch (Exception _)
        {
            ex = _;
        }
    });
    if (ex != default(Exception))
        throw ex;
}

それも役に立ちませんでした。

Async CTP 更新のインストールがホースされている可能性があると思います。

このコードが期待どおりに機能するか (「失敗」ではなく「成功」)、またはそのように機能することが「想定」されていません。そうでない場合、どのように回避しますか?

4

1 に答える 1

5

表示されている動作は、おそらくエッジ ケースのバグであるか、直感的でない場合でも正しい可能性があります。通常、非同期メソッドを同期的に呼び出すと、タスクがラップアラウンドして実行されます。タスクの終了を待っている人がいないため、例外がメインスレッドに到達することはありません。Main を直接呼び出すと成功しますが、ランタイムは別のスレッドで「成功」の例外を確認します。

main はアプリケーションのエントリポイントであるため、同期的に呼び出され、エントリポイントが Task ラッピング動作をトリガーしない可能性が高いため、await が適切に実行されず、TaskEx.Run が独自のスレッドでスローされます。別のスレッドでスローされる例外としてのランタイム。

main をメソッドとして実行する場合async、つまり aを返しTask(返す anは実際には を介し​​てのみ呼び出すことができるため)、同期メイン コンテキストからそれをブロックすると、以下のテストが示すように適切な動作が得られます。asyncvoidawait

static async Task Main() {
    try {
        await TaskEx.Run(() => { throw new Exception("failure"); });
    } catch(Exception) {
        throw new Exception("success");
    }
}

static async Task Main2() {
    await Main();
}

[Test]
public void CallViaAwait() {
    var t = Main2();
    try {
        t.Wait();
        Assert.Fail("didn't throw");
    } catch(AggregateException e) {
        Assert.AreEqual("success",e.InnerException.Message);
    }
    }


[Test]
public void CallDirectly() {
    var t = Main();
    try {
        t.Wait();
        Assert.Fail("didn't throw");
    } catch(AggregateException e) {
        Assert.AreEqual("success", e.InnerException.Message);
    }
}

つまり、Taskは、内部例外として成功AggregateException例外を含む で失敗します。

于 2011-06-16T19:40:20.893 に答える