2010-03-09 17 views
8

Mi aplicación de prueba WPF (muy simple, solo una ventana) está utilizando una dll administrada por un tercero (digamos X.dll). Este dll administrado usa algunos dll no administrados. Digamos que escribo una pequeña aplicación wpf que solo hace referencia a X.dll. Y en el constructor de la ventana accedo a algo dentro de X.dll (es decir, en algún espacio de nombres en X.dll). Al hacer esto, no veo ninguna excepción y parece que las cosas continúan como se esperaba. Pero al regresar el control de tiempo de ejecución de .NET, consigo una excepción en 'DispatcherUnhandledException' manejador de clase de aplicación: “desbordamiento positivo o negativo en la operación aritmética”"Desbordamiento o subdesbordamiento en la operación aritmética" Problema específico de WPF

System.ArithmeticException fue controlada mensaje = "desbordamiento o underflow en la operación aritmética ".
Fuente = "PresentationFramework"
StackTrace:

System.Windows.Window.ValidateTopLeft(Double length)
System.Windows.Window.CoerceTop(DependencyObject d, Object value) System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean skipBaseValueChecks)
System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, OperationType operationType)
System.Windows.DependencyObject.CoerceValue(DependencyProperty dp) at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
System.Windows.Window.CreateSourceWindowImpl() at System.Windows.Window.SafeCreateWindow() at System.Windows.Window.ShowHelper(Object booleanBox)
System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)

Algunos puntos:

  • Esto sólo ocurre en WPF aplicación y no en winforms aplicación.
  • Esto no queda atrapado en un try-catch. solo en Application DispatcherUnhandledException
  • Esto no ocurre si accedo al código de X.dll dentro del evento 'Cargado' de la ventana, solo ocurre en el constructor.

¿Alguien puede adivinar el problema?

Gracias, Mishal

+0

Cuando dice "acceder", quiere decir que está pasando el valor como argumento para algo, ¿no? ¿A qué lo estás pasando? – Jay

+0

Si accedo/leo el entero XNameSpace.AStaticClass.StatInt (donde XNamespace es un espacio de nombres dentro de X.dll) y lo almaceno en otro entero, veo esto. Además, veo que si pongo la declaración en try catch entonces no queda atrapada. Solo queda atrapado en el controlador DispatcherUnhandledException de System.Window.Application ... eso es realmente extraño. – mishal153

Respuesta

5

No estoy seguro de la causa todavía, pero la solución está aquí:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/a31f9c7a-0e15-4a09-a544-bec07f0f152c

parece ser un error muy popular :)

gracias, Mishal

+0

Solo por los demás, la solución propuesta en el enlace es más parecida a una solución alternativa. El problema en sí parece ser un error en WPF, aunque no estoy seguro si todavía hay un problema de conexión en este. – jpierson

+0

https://connect.microsoft.com/VisualStudio/feedback/details/382052/cryptic-arithmeticexception-in-system-double-equals-during-wpf-layout – jpierson

10

Siguiendo el enlace de @Mishhl, la solución es

public class FloatingPointReset 
{ 
    [DllImport("msvcr110.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern int _fpreset(); 


    public static void Action() 
    { 
     // Reset the Floating Point (When called from External Application there was an Overflow exception) 
     _fpreset(); 
    } 
} 

Es causado por algo en una DLL incluida que restablece el FP en un estado que no es compatible con WPF/C#/Microsoft DLL. Delphi/CPPB hace esto por defecto.

Así que, ya sea en el constructor de la ventana o aplicación() constructor acaba de hacer

FloatingPointReset.Action(); 

Es posible que necesite cambiar el siguiente para hacer referencia a cualquier versión de msvcr ###. Dll

[DllImport("msvcr110.dll", CallingConvention = CallingConvention.Cdecl)] 

por ejemplo,

[DllImport("msvcr70.dll", CallingConvention = CallingConvention.Cdecl)] 
+0

Mi sugerencia es llamar a _fpreset no solo en constructor sino antes y después de llamadas a funciones externas. Tengo este problema al llamar funciones desde la biblioteca de objetos COM de la 3ª parte. – Denis

+0

Para mí lo resolví siguiendo la biblioteca externa que estoy usando y sabía qué msvcrXX.dll está usando (era msvcr100.dll), luego llamé a ** FloatingPointReset.Action(); ** justo antes de llamar a ** base.OnRender (drawingContext); ** en mi UserControl. – Dabbas

0

Si puede ayudar, yo estaba teniendo el mismo problema (como se indica aquí y here). Traigo aquí una de las posibles causas de esto.

Estoy usando ElementHost (C#, .net4.0, winform, VS2012) para obtener un gran UserControl de WPF. Todo funcionaba bien. En mi código de usuario UserControl, estaba usando una clase que estaba procesando desde otra DLL, usada para almacenar la progresión de cierta tarea. Por ejemplo (que está cerca de la realidad):

public class SI_MyProgressionHelper 
{ 
    public string gstr_OverallProgress_Description { get; set; } 

    public int gint_OverallProgress_ActualValue { get; set; } 
    public int gint_OverallProgress_MaximumValue { get; set; } 
} 

entonces yo quería "tapón" que en mi clase de WPF progressBar/cuadro de texto para informar de la progresión a medida que avanza. Sin embargo (y eso es otra conversación), WPF necesita tener INotifyPropertyChanged aplicado a cada propiedad que desee conectar en WPF (para actualizar automáticamente los controles en WPF). Esa es una de las cosas más feas que he visto, pero es lo que es (Y sé que debo perder algo ...)

De todos modos, para cumplir con el mecanismo WPF vinculante entre mi ProgressBar/textbox y mi clase SI_MyProgressionHelper, i he modificado la clase (que repito, está en otra DLL) a esto:

public class SI_MyProgressionHelper : INotifyPropertyChanged 
{ 
    private string _gstr_OverallProgress_Description = ""; 
    public string gstr_OverallProgress_Description { get { return _gstr_OverallProgress_Description; } set { _gstr_OverallProgress_Description = value; RaisePropertyChanged("gstr_OverallProgress_Description"); } } 

    private int _gint_OverallProgress_ActualValue = 0; 
    public int gint_OverallProgress_ActualValue { get { return _gint_OverallProgress_ActualValue; } set { _gint_OverallProgress_ActualValue = value; RaisePropertyChanged("gint_OverallProgress_ActualValue"); } } 

    private int _gint_OverallProgress_MaximumValue = 9999; 
    public int gint_OverallProgress_MaximumValue { get { return _gint_OverallProgress_MaximumValue; } set { _gint_OverallProgress_MaximumValue = value; RaisePropertyChanged("gint_OverallProgress_MaximumValue"); } } 


    protected virtual void RaisePropertyChanged(string propName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

¡BAM! El error ocurre en cualquier propiedad de entero aleatorio de cualquier elemento de XMLElement (alto, ancho, etc.) de mi UserContrl (exactamente como se indica aquí y en la otra referencia que indiqué en la parte superior).

La aplicación de la solución traído aquí no corregir mi problema: En mi método Program.cs Principal():

[DllImport("msvcr70.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern int _fpreset(); 

y luego, en mis UserControl.xaml.cs, en el constructor:

public UserControl1() 
{ 
    Program._fpreset(); 
    InitializeComponent(); 
} 

también, y esa es la razón por la que escribí ese comentario: quitando el INotifyPropertyChanged en mi clase auxiliar (y otras cosas relacionadas), el problema desaparece. (pero mi WPF está triste porque mi código es demasiado corto para él).

Espero que esta información adicional pueda ayudar a alguien que tenga el mismo problema.

Además, para toda mi colega francés, aquí está el error encontrado francés:

il y una eu ONU dépassement de capacité positif ou négatif dans l'opération arithmétique.

Cuestiones relacionadas