如何在任务生成事件时从任务中获取异常

时间:2010-11-25 09:08:38

标签: c# system.reactive

我有以下情况。生成事件并可能抛出异常的Task

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

一切都很简单。我使用Observable.FromEvent收听事件:

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

当没有异常发生时,这一切都正常。但是,当任务抛出异常时,我想在我的观察中知道这一点。该异常现在在任务中“隐藏”。

我是否可以通过在发生异常时创建另一个事件,将其包装在IObservable内并订阅此新的observable来实现此目的?或者有更简单的方法吗?

1 个答案:

答案 0 :(得分:2)

这个怎么样:

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

输出结果为:

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:发生一个或多个错误。 ---&GT; System.Exception:抛出了类型'System.Exception'的异常。    在RxDisposeTests.Program。&lt;&gt; c_ DisplayClass9.b _0()在C:\ Users \ Richard.Hein \ Documents \ Visual Studio 2010 \ Projects \ RxConsole \ RxDisposeTests \ Program.cs:line 25    在System.Threading.Tasks.Task.InnerInvoke()    在System.Threading.Tasks.Task.Execute()    ---内部异常堆栈跟踪结束--- ---&GT; (内部异常#0)System.Exception:抛出了类型'System.Exception'的异常。    在RxDisposeTests.Program。&lt;&gt; c_ DisplayClass9.b _0()在C:\ Users \ Richard.Hein \ Documents \ Visual Studio 2010 \ Projects \ RxConsole \ RxDisposeTests \ Program.cs:line 25    在System.Threading.Tasks.Task.InnerInvoke()    在System.Threading.Tasks.Task.Execute()&lt; ---

修改

不确定TakeUntil是否是一个好的解决方案,因为Task可能会返回除Exceptions之外的其他内容,对吧?所以这可行:

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