【问题标题】:"Overflow or underflow in the arithmetic operation" WPF specific issue“算术运算中的溢出或下溢” WPF 特定问题
【发布时间】:2011-01-25 07:25:12
【问题描述】:

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

“算术运算中的上溢或下溢。” System.ArithmeticException 未处理 Message="算术运算中的溢出或下溢。"
来源="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)

几点:

  • 这仅发生在 WPF 应用程序中,而不发生在 winforms 应用程序中。
  • 这不会被 try-catch 捕获。仅在应用程序的 DispatcherUnhandledException 中
  • 如果我在 Window 的“Loaded”事件中访问 X.dll 的代码,则不会发生这种情况,只会在构造函数中发生。

谁能猜出问题所在?

谢谢, 米沙尔

【问题讨论】:

  • 当您说“访问”时,您的意思是您将值作为参数传递给某些东西,对吗?你把它传递给什么?
  • 如果我访问/读取整数 XNameSpace.AStaticClass.StatInt(其中 XNamespace 是 X.dll 中的命名空间)并将其存储在另一个整数中,我会看到这一点。此外,我看到如果我将语句放在 try catch 中,它就不会被捕获。它只在 System.Window.Application 的 DispatcherUnhandledException 处理程序中被捕获......这真的很奇怪。

标签: c# wpf


【解决方案1】:

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

似乎是一个流行的错误:)

谢谢, 米沙尔

【讨论】:

【解决方案2】:

按照@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)]

例如

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

【讨论】:

  • 我的建议是不仅在构造函数中调用 _fpreset,而且在外部函数调用之前和之后调用。从第 3 部分 COM 对象库调用函数时,我遇到了这个问题。
  • 对我来说,我通过遵循我正在使用的外部库并知道它正在使用哪个 msvcrXX.dll(它是 msvcr100.dll)来解决它,然后我调用了 FloatingPointReset.Action(); 在我的 UserControl 中调用 base.OnRender(drawingContext); 之前。
【解决方案3】:

如果有帮助,我遇到了完全相同的问题(如此处所述和 here)。我在这里提出了一个可能的原因。

我将 ElementHost(c#、.net4.0、winform、VS2012)用于出色的 WPF 用户控件。 一切正常。在我的 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/文本框和我的 SI_MyProgressionHelper 类之间的 WPF 绑定机制,我已将类(我重复一遍,在另一个 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;
}

砰!该错误发生在我的 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 un dépassement de capacité positif ou négatif dans l'opération arithmétique。

【讨论】:

  • 我遇到了同样的错误,但我没有使用 msvcr70.dll。是否有可能找出哪个 DLL 导致了类似的错误?以及如何?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多