Причина появления System.ArithmeticException?

Есть проект (Hello Word). Одно окно, одна кнопка и поле TextBox. CodeBehind:
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ShowForm(5);            
        }

        [DllImport(@"pcv.dll", SetLastError = true, EntryPoint = "_ShowForm", CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public extern static int ShowForm(int hwnd);        
    }


По нажатию кнопки открывается форма из pcv.dll. Закрываю форму и устанавливаю фокус на TextBox. Вылетает ошибка:

Необработанное исключение типа "System.ArithmeticException" в WindowsBase.dll. Дополнительные сведения: Переполнение или потеря точности в арифметической операции.

в System.Windows.Size..ctor(Double width, Double height)
   в System.Windows.Documents.AdornerLayer.InvalidateAdorner(AdornerInfo adornerInfo)
   в System.Windows.Documents.AdornerLayer.UpdateElementAdorners(UIElement element)
   в System.Windows.Documents.AdornerLayer.UpdateAdorner(UIElement element)
   в System.Windows.Documents.AdornerLayer.Add(Adorner adorner, Int32 zOrder)
   в System.Windows.Documents.CaretElement.EnsureAttachedToView()
   в System.Windows.Documents.CaretElement.Update(Boolean visible, Rect caretRectangle, Brush caretBrush, Double opacity, Boolean italic, CaretScrollMethod scrollMethod, Double scrollToOriginPosition)
   в System.Windows.Documents.TextSelection.UpdateCaretStateWorker(Object o)
   в System.Windows.Documents.TextSelection.UpdateCaretState(CaretScrollMethod caretScrollMethod)
   в System.Windows.Documents.TextSelection.EnsureCaret(Boolean isBlinkEnabled, Boolean isSelectionActive, CaretScrollMethod scrollMethod)
   в System.Windows.Documents.TextSelection.System.Windows.Documents.ITextSelection.UpdateCaretAndHighlight()
   в System.Windows.Documents.TextEditor.OnGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
   в System.Windows.Controls.Primitives.TextBoxBase.OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
   в System.Windows.UIElement.OnGotKeyboardFocusThunk(Object sender, KeyboardFocusChangedEventArgs e)
   в System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   в System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   в System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   в System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   в System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   в System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   в System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   в System.Windows.Input.InputManager.ProcessStagingArea()
   в System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   в System.Windows.Input.KeyboardDevice.ChangeFocus(DependencyObject focus, Int32 timestamp)
   в System.Windows.Input.KeyboardDevice.TryChangeFocus(DependencyObject newFocus, IKeyboardInputProvider keyboardInputProvider, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
   в System.Windows.Input.KeyboardDevice.Focus(DependencyObject focus, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
   в System.Windows.Input.KeyboardDevice.Focus(IInputElement element)
   в System.Windows.UIElement.Focus()
   в System.Windows.Documents.TextEditorMouse.MoveFocusToUiScope(TextEditor This)
   в System.Windows.Documents.TextEditorMouse.OnMouseDown(Object sender, MouseButtonEventArgs e)
   в System.Windows.Controls.Primitives.TextBoxBase.OnMouseDown(MouseButtonEventArgs e)
   в System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e)
   в System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   в System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   в System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   в System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   в System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   в System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   в System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   в System.Windows.Input.InputManager.ProcessStagingArea()
   в System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   в System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   в System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   в System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   в System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   в MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   в MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   в System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   в MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   в System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   в MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   в MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   в System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   в System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   в System.Windows.Threading.Dispatcher.Run()
   в System.Windows.Application.RunDispatcher(Object ignore)
   в System.Windows.Application.RunInternal(Window window)
   в System.Windows.Application.Run(Window window)
   в System.Windows.Application.Run()
   в WpfApplication1.App.Main() в d:\Test\WpfApplication1\obj\Debug\App.g.cs:строка 0
   в System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   в System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   в System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   в System.Threading.ThreadHelper.ThreadStart()
  • Вопрос задан
  • 1277 просмотров
Решения вопроса 1
artemmatveev
@artemmatveev Автор вопроса
Определённые функции некоторых версий Delphi, c++ любят менять бит в FPU-регистре CW на такое значение, что бедный математический сопроцессор перестаёт переваривать double.NaN, начиная плеваться на него исключениями. А в WPF, как известно, у доброй половины свойств FrameworkElement-а значение по умолчанию выставлено именно в NaN. При малейших манипуляциях над этими свойствами приложение начинает падать.


Регистр управления CW предназначен для управления режимами работы сопроцессора. Он содержит ряд полей, значения которых влияют на точность результата, поведение процессора при встрече некорректных операндов и результатов


Решение проблемы стало, как и предложил Sumor, но только на стороне .NET-а:

public partial class MainWindow : Window
    {
        const int _RC_NEAR = 0x00000000;
        const int _PC_53 = 0x00010000;
        const int _EM_INVALID = 0x00000010;
        const int _EM_UNDERFLOW = 0x00000002;
        const int _EM_ZERODIVIDE = 0x00000008;
        const int _EM_OVERFLOW = 0x00000004;
        const int _EM_INEXACT = 0x00000001;
        const int _EM_DENORMAL = 0x00080000;
        const int _CW_DEFAULT = _RC_NEAR + _PC_53 + _EM_INVALID + _EM_ZERODIVIDE + _EM_OVERFLOW + _EM_UNDERFLOW + _EM_INEXACT + _EM_DENORMAL;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {            
            int hwnd = ShowForm(5);
            _controlfp(_CW_DEFAULT, 0xfffff);
        }

        [DllImport(@"pcv.dll", SetLastError = true, EntryPoint = "_ShowForm", CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
        public extern static int ShowForm(int hwnd);

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int _controlfp(int newControl, int mask);

    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Sumor
Первое - действительно проверьте правильность соглашения о вызове, т.е. атрибута CallingConvention.
Второе - если есть исходники pcv.dll, то нужно в самое начало добавить вызов:
если Delphi
Set8087CW($133F);
или если c++
_controlfp(_CW_DEFAULT, 0xfffff);
Объяснение "магии" по ссылке PRB: System.Arithmetic Exception Error When You Ch...
Ответ написан
Neuroware
@Neuroware
Программист в свободное от работы время
убрать фокус в поле
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы