使用Observable.Interval
时,我得到以下异常导致应用程序崩溃的几次(异常只能在事件查看器中找到 - 错误源:.NET运行时)
Application: RxPlayground.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentNullException
Stack:
at System.Reactive.Concurrency.AsyncLock.Wait(System.Action)
at System.Reactive.Concurrency.DefaultScheduler+<>c__DisplayClass9`1[[System.Int64, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].<SchedulePeriodic>b__6()
at System.Reactive.Concurrency.ConcurrencyAbstractionLayerImpl+PeriodicTimer.Tick(System.Object)
at System.Threading.TimerQueueTimer.CallCallbackInContext(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
使用Reactive Extensions时遇到过这样的问题吗?你知道原因是什么吗?
以下是一些可能导致问题的代码(但可能不是因为我无法重现它...):
static void Main(string[] args)
{
var subscriptions = SubscribeToObservables().Take(10000).ToArray();
Console.WriteLine("BEGIN. Click Enter to Dispose...");
Console.ReadLine();
Console.WriteLine("DISPOSING");
foreach (var subscription in subscriptions)
{
subscription.Dispose();
}
Console.WriteLine("DISPOSED. Click Enter to finish...");
Console.ReadLine();
Console.WriteLine("END");
}
private static IEnumerable<IDisposable> SubscribeToObservables()
{
var x = Observable.Interval(TimeSpan.FromSeconds(1)).Select(n =>
{
//Thread.Sleep(TimeSpan.FromMinutes(1));
return n;
});
var sub = x.Subscribe(
n =>
{
Thread.Sleep(TimeSpan.FromMinutes(1));
Console.WriteLine(n);
});
yield return sub;
}
编辑:我检查了AsyncLock
类及其所有引用(https://github.com/Reactive-Extensions/Rx.NET/blob/master/Rx.NET/Source/System.Reactive.Core/Reactive/Concurrency/AsyncLock.cs),我看不到Action委托可能为空的任何可能性!在我们的异常情况下,我们可以从stacktrace中看到从以下代码(https://github.com/Reactive-Extensions/Rx.NET/blob/master/Rx.NET/Source/System.Reactive.Core/Reactive/Concurrency/DefaultScheduler.cs)调用了Wait:
public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action)
{
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException("period");
if (action == null)
throw new ArgumentNullException("action");
var state1 = state;
var gate = new AsyncLock();
var cancel = s_cal.StartPeriodicTimer(() =>
{
gate.Wait(() =>
{
state1 = action(state1);
});
}, period);
return Disposable.Create(() =>
{
cancel.Dispose();
gate.Dispose();
action = Stubs<TState>.I;
});
}
我已经在IL DASM中检查过 System.Reactive.Concurrency.DefaultScheduler +&lt;&gt; c__DisplayClass9`1 [[System .__ Canon,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089] ] .b__6()是为以下lambda编译的:
() =>
{
gate.Wait(() =>
{
state1 = action(state1);
});
}
看起来lambda () => { state1 = action(state1); }
被传递为null。 但是怎么可能?
答案 0 :(得分:1)
可以重现异常。你必须传递一个选择器函数,它只是null。也许你忘了在每种情况下初始化Select块中的函数。或者当调度程序想要运行它时,类的实例不再存在。这是可能的方式:
Func<long, int> selector = null;
var x = Observable.Interval(TimeSpan.FromSeconds(1)).Select(selector);