TimeSpan.FromSeconds (-1.0) и double.NaN - PullRequest
2 голосов
/ 04 марта 2009

Мы создаем приложение WPF и наблюдаем случайное и очень странное поведение, которое, похоже, происходит из-за BCL. Мы получаем необработанное исключение со следующей трассировкой стека:

[ArgumentException], 
"TimeSpan does not accept floating point Not-a-Number values."
   at System.TimeSpan.Interval(Double value, Int32 scale)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)

Теперь, если верить Reflector, вызывающий метод (Dispatcher.Invoke) вызывает

...,TimeSpan.FromSeconds(-1.0),...

, который выдает исключение Argument, потому что передаваемый аргумент возвращает true в double.IsNaN. Это явно не имеет никакого смысла, и мы находим это, по меньшей мере, странным.

Нам не удалось воспроизвести это поведение в каких-либо небольших выборках, поэтому мы ищем способы определить причину этого (и других, по-видимому, связанных исключений TimeSpan, которые также генерируются) в нашем полном приложении. У нас есть ряд вопросов, которые, мы надеемся, кто-то может нам помочь, так как нам не повезло в поисках чего-то подобного

  • Кто-нибудь видел такое поведение или распознавал симптомы
  • В чем причина этого, казалось бы, случайного поведения в базовой математике, мы как-то портим стек или кучу?
  • Можем ли мы каким-то образом отладить IL в TimeSpan.Interval (возможно, WinDbg?), Разбить и проверить стек / кучу для проверки значений?

Наше приложение имеет большой объем данных, с большим количеством асинхронных данных и большим количеством привязок к данным, но мы не видим, чтобы курящий пистолет направил на это что-либо из следов стека, которые нам удалось получить.

Просто чтобы прояснить вопрос: кто-нибудь видел описанное поведение раньше, распознает симптомы или имеет информацию о том, как мы можем отладить ситуацию?

Мысли, комментарии, идеи, предложения?

Ответы [ 4 ]

1 голос
/ 04 марта 2009

Быстрая заметка о трассировке стека, вызовы методов могут быть встроены, если они соответствуют определенным требованиям. Для получения дополнительной информации читайте http://blogs.msdn.com/ericgu/archive/2004/01/29/64717.aspx

Код IL для вызова Dispatcher.Invoke:

L_0002: ldc.r8 -1
L_000b: call valuetype [mscorlib]System.TimeSpan [mscorlib]System.TimeSpan::FromMilliseconds(float64)

Мой тестовый код, C #:

double d = -1.0;
TimeSpan t = TimeSpan.FromMilliseconds(d);

Который становится следующим IL-кодом:

L_0001: ldc.r8 -1
L_000a: stloc.0 
L_000b: ldloc.0 
L_000c: call valuetype [mscorlib]System.TimeSpan [mscorlib]System.TimeSpan::FromMilliseconds(float64)

Я не могу повторить вашу проблему, даже при передаче точно такого же значения в TimeSpan.FromMilliseconds

1 голос
/ 04 марта 2009
1.0/0 

=> NaN Положительная бесконечность

Думал о 0/0.0: |

1 голос
/ 04 марта 2009

Я не уверен, что правильно понял ваш вопрос, но не думаю, что -1.0 - это NaN.

РЕДАКТИРОВАТЬ (Чтобы решить реальную проблему): Вы можете скачать символы .NET Framework и отладить их, чтобы увидеть фактическое значение переменной, переданной в TimeSpan.FromSeconds, и все, что может происходить.

0 голосов
/ 04 марта 2009

возможно, что оптимизируется большая часть трассировки стека, и у вас есть некоторый код, который делает вещи с временными панелями, которые не отображаются.

EDIT:

в отражателе я вижу вызов Dispatcher.Invoke Timespan.FromMilliseconds, который вызывает Timespan.Interval. Но в трассировке стека мы видим только Dispatcher.Invoke и Timespan.Interval, поэтому Timespan.FromMilliseconds остается вне трассировки стека. если мы предполагаем, что методы могут быть исключены из трассировки стека, то, возможно, существует совершенно другой путь к Timespan.Interval. сказать:

</p> <pre> Dispatcher.Invoke Dispatcher.InvokeImpl Dispatcher.BeginInvoke - Call into your code or somewhere else in BCL - Timespan.Interval </pre> <p>

если потоком управления является Dispatcher.Invoker-> Timepan.FromMilliseconds -> Timespan.Interval, то я бы заподозрил ошибку компиляции JIT или какое-либо повреждение из собственного кода, который выполняется заранее.

вот страница о том, как увидеть код, сгенерированный JIT: http://blogs.msdn.com/vancem/archive/2006/02/20/535807.aspx

...