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

问题描述 投票:0回答:3

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

“算术运算中的上溢或下溢。” System.ArithmeticException 未处理 Message="算术运算中溢出或下溢。"
来源="演示框架"
堆栈跟踪

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 的代码,则不会发生这种情况,只会发生在构造函数中。

有人能猜出问题所在吗?

谢谢, 米沙尔

c# wpf
3个回答
14
投票

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

8
投票

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

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


4
投票

如果它可以帮助的话,我遇到了完全相同的问题(如此处所述和 这里)。我在这里带来了可能的原因之一。

我正在使用 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 进度条/文本框中以报告进度。然而(这是另一个话题),WPF 需要将 INotifyPropertyChanged 应用于您想要插入 WPF 中的每个属性(以自动更新 WPF 中的控件)。这是我见过的最丑陋的事情之一,但它就是这样(我知道我一定错过了一些东西..)

无论如何,为了遵守我的 ProgressBar/textbox 和 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很伤心,因为我的代码对他来说太短了)。

希望这些附加信息可以帮助遇到同样问题的人。

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

我是一个积极或消极能力丧失的人 算术运算。

© www.soinside.com 2019 - 2024. All rights reserved.