3 Stimmen

Wie erhält man eine Ausnahme von einer Aufgabe, wenn die Aufgabe Ereignisse erzeugt?

Ich habe das folgende Szenario. A Task die Ereignisse erzeugt und eine Ausnahme auslösen kann:

public event EventHandler<EventArgs> MyEvent;
new Task(() =>
    {
        while (condition)
        {
            // Generate standard .NET event.
            MyEvent(this, new EventArgs());

            // Maybe throw exception.
            if (somethingIsWrong) throw new Exception();
        }
    });

Alles ganz einfach. Ich höre mir die Ereignisse mit Observable.FromEvent :

var events =
    Observable.FromEvent<EventArgs>(h => myClass.MyEvent += h,
                                    h => myClass.MyEvent -= h);
events.Subscribe(
    ev => DoSomethingOnNext(ev),
    ex => DoSomethingOnError(ex),
    () => DoSomethingOnCompleted());

Dies alles funktioniert einwandfrei, wenn keine Ausnahme auftritt. Wenn eine Ausnahme von der Aufgabe ausgelöst wird, möchte ich dies jedoch in meinem Observable wissen. Die Ausnahme ist jetzt "versteckt" innerhalb der Aufgabe.

Kann ich dies nur tun, indem ich ein anderes Ereignis erstelle, wenn die Ausnahme auftritt, und es in ein IObservable und dieses neue Observatorium zu abonnieren? Oder gibt es einen einfacheren Weg?

2voto

Wie wäre es damit:

class Program
{
    public event EventHandler<EventArgs> MyEvent;
    static void Main(string[] args)
    {
        var myClass = new Program();            

        var task = new Task(() =>
        {
            for(var i=0; i<5; i++) {
                // Generate standard .NET event. 
                myClass.MyEvent(myClass, new EventArgs());
            }

            throw new Exception();
        });

        var obsTask = task.ToObservable();

        var events = Observable.FromEvent<EventArgs>(h => myClass.MyEvent += h, h => myClass.MyEvent -= h);            

        events.TakeUntil(obsTask).Subscribe(
            ev => DoSomethingOnNext(ev), 
            ex => DoSomethingOnError(ex),
            () => DoSomethingOnCompleted());

        task.Start();

        Console.ReadKey();
    }

    private static void DoSomethingOnCompleted()
    {
        Console.WriteLine("DoSomethingOnCompleted");
    }

    private static void DoSomethingOnError(Exception ex)
    {
        Console.WriteLine("DoSomethingOnError:" + ex.ToString());
    }

    private static void DoSomethingOnNext(IEvent<EventArgs> ev)
    {
        Console.WriteLine("DoSomethingOnNext:" + ev.ToString());
    }

Die Ausgabe ist:

DoSomethingOnNext:System.Collections.Generic.Event 1[System.EventArgs] DoSomethingOnNext:System.Collections.Generic.Event 1[System.EventArgs] DoSomethingOnNext:System.Collections.Generic.Event 1[System.EventArgs] DoSomethingOnNext:System.Collections.Generic.Event 1[System.EventArgs] DoSomethingOnNext:System.Collections.Generic.Event`1[System.EventArgs] DoSomethingOnError:System.AggregateException: Ein oder mehrere Fehler sind aufgetreten. ---> System.Exception: Eine Ausnahme vom Typ 'System.Exception' wurde ausgelöst. at RxDisposeTests.Program.<>c_ AnzeigeKlasse9.b _0() in C:\Users\Richard.Hein\Documents\Visual Studio 2010 \Projects\RxConsole\RxDisposeTests\Program.cs :Zeile 25 bei System.Threading bei System.Threading.Tasks.Task.Execute() --- Ende der Stapelverfolgung der inneren Ausnahme --- ---> (Innere Ausnahme #0) System.Exception: Eine Ausnahme vom Typ 'System.Exception' wurde ausgelöst. at RxDisposeTests.Program.<>c_ AnzeigeKlasse9.b _0() in C:\Users\Richard.Hein\Documents\Visual Studio 2010 \Projects\RxConsole\RxDisposeTests\Program.cs :Zeile 25 bei System.Threading at System.Threading.Tasks.Task.Execute()<---

EDITです:

Nicht sicher, ob TakeUntil eine gute Lösung ist, weil Task etwas anderes als Ausnahmen zurückgeben könnte, richtig? Also könnte dies funktionieren:

var events = Observable.CreateWithDisposable<IEvent<EventArgs>>(observer =>
{
    var eventObs = Observable.FromEvent<EventArgs>(
        h => myClass.MyEvent += h, h => myClass.MyEvent -= h);
    task.ToObservable().Subscribe(_ => { }, observer.OnError, observer.OnCompleted);
    return eventObs.Subscribe(observer.OnNext, observer.OnError, observer.OnCompleted);
});

events.Subscribe(
    ev => DoSomethingOnNext(ev), 
    ex => DoSomethingOnError(ex),
    () => DoSomethingOnCompleted());

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X