“算术运算中的溢出或下溢”WPF特定问题

时间:2010-03-09 06:23:09

标签: c# wpf

我的WPF测试应用程序(非常简单,只有一个窗口)正在使用第三方托管的dll(比如X.dll)。这个托管的dll使用了一些非托管的dll。 所以我可以说我写了一个只引用X.dll的小wpf应用程序。在窗口的构造函数中,我访问X.dll内部的某些内容(即在X.dll中的某些命名空间中)。在这样做时,我没有发现任何异常,似乎事情按预期进行。但是在将控件返回给.NET运行时,我在Application类的'DispatcherUnhandledException'处理程序中得到一个异常:

“算术运算中出现溢出或下溢。” System.ArithmeticException未处理 消息 =“算术运算中溢出或下溢。”
来源 = “PresentationFramework”
栈跟踪

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)

有些观点:

  • 这仅发生在WPF应用中,而不是在winforms应用中。
  • 这不会陷入尝试捕获。仅在Application的DispatcherUnhandledException
  • 如果我在Window的'Loaded'事件中访问X.dll的代码,则不会发生这种情况,只会在构造函数中发生。

有人可以猜出这个问题吗?

谢谢, 米沙勒

3 个答案:

答案 0 :(得分:10)

根据@Mishhl的链接,修复是

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

它是由包含的DLL中的某些内容将FP重置为与WPF / C#/ Microsoft DLL不兼容的状态引起的。 Delphi / CPPB默认执行此操作。

所以在窗口构造函数或App()构造函数中只需执行

FloatingPointReset.Action();

您可能需要更改以下内容以引用任何版本的msvcr ###。dll

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

e.g。

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

答案 1 :(得分:5)

我还不确定根本原因,但解决方法是在这里:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/a31f9c7a-0e15-4a09-a544-bec07f0f152c

似乎是一个受欢迎的错误:)

感谢, 米沙勒

答案 2 :(得分:1)

如果可以提供帮助,我遇到了完全相同的问题(如此处所述) here)。我带来了一个可能的原因。

我正在使用ElementHost(c#,。net4.0,winform,VS2012)来获得出色的WPF UserControl。 一切都很棒。在我的UserControl后台代码中,我使用的是一个从另一个DLL进行编码的类,用于存储某些任务的进度。例如(它接近现实):

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

然后我想把这个类“插入”我的WPF progressBar / textBox来报告进展情况。但是(这是另一个对话),WPF需要将INotifyPropertyChanged应用于要插入WPF的每个属性(以自动更新WPF中的控件)。这是我见过的最丑陋的东西之一,但它就是它(而且我知道我必须错过一些东西......)

无论如何,为了遵守我的ProgressBar / textbox和我的SI_MyProgressionHelper类之间的WPF Binding mecanism,我已经修改了类(我重复一遍,在另一个DLL中):

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!错误发生在我的UserContrl的任何XMLElement(高度,宽度等等)的任何随机整数属性上(完全如此处和我在顶部所述的其他参考中所述)。

应用此处带来的解决方案可以解决我的问题: 在我的Program.cs Main()方法中:

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

然后,在我的UserControl.xaml.cs中,在构造函数中:

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

此外,这就是我写这篇评论的原因:通过删除我的Helper类上的INotifyPropertyChanged(和其他相关内容),问题消失。 (但我的WPF很难过,因为我的代码对他来说太短了)。

希望这些额外的信息可以帮助有同样问题的人。

另外,对于我所有的法国同事,这里遇到法语错误:

  

Il y a eu undepassementdecapacitépositifounégatifdans   l'opérationarithmétique。