Domanda

Questo esempio di "errore":

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

Che è, l'eccezione con il testo "fallimento" bolle.

Poi ho provato questa soluzione:

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;
}

Che non aiutano.

Suppongo che il mio Async CTP di aggiornamento di installazione potrebbe essere hosed.

Se questo codice funziona come mi aspetto ("successo" bolle "(e non "fallimento"), o non è, questo "dovrebbe" lavorare in quel modo.E se non, come si potrebbe risolvere?

È stato utile?

Soluzione

Il problema riscontrato è probabilmente un caso limite bug o può anche essere corretto, se non intuitive.Normalmente, quando si richiama un metodo asincrono sincrono, si avvolge di un'attività in giro per l'esecuzione e dal momento che non c'è nessuno in attesa, con il compito di finitura, l'eccezione non rende il thread principale.Se si dovesse chiamare Principale direttamente che sarebbe successo, ma poi runtime vorresti vedere un'eccezione di "successo" in un altro thread.

Dato principale è il punto di ingresso dell'applicazione, è invocato in modo sincrono e probabile che, come il punto di ingresso non attivare l'Attività di avvolgimento comportamento, in modo che attendono non è eseguita correttamente e il TaskEx.Eseguire getta sul suo thread, che si presenta in fase di esecuzione, come un'eccezione generata in un altro thread.

Se si esegue come un async metodo, cioèla restituzione di un Task (dal momento che un async che restituisce void può veramente solo essere chiamato via await) e il blocco su di esso dal vostro sincrono contesto, si dovrebbe ottenere il comportamento appropriato come il seguente test illustra:

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);
    }
}

I. e.il Compito difetti con un AggregateException che contiene il successo un'eccezione è l'eccezione interna.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top