【发布时间】:2016-08-29 22:02:16
【问题描述】:
我遇到了可能是我见过的最没用的异常(在 VBA 之外),System.ComponentModel.Win32Exception: "The operation completed successfully"
堆栈跟踪:
at MS.Win32.UnsafeNativeMethods.CreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at System.Windows.Interop.HwndSource.Initialize(HwndSourceParameters parameters)
at System.Windows.Interop.HwndSource..ctor(HwndSourceParameters parameters)
at System.Windows.Controls.Primitives.Popup.PopupSecurityHelper.BuildWindow(Int32 x, Int32 y, Visual placementTarget, Boolean transparent, HwndSourceHook hook, AutoResizedEventHandler handler)
at System.Windows.Controls.Primitives.Popup.BuildWindow(Visual targetVisual)
at System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean asyncCall)
at System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean dependencySourcesChanged, Boolean initialValue, Boolean isASubPropertyChange)
at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
at MS.Internal.Data.ClrBindingWorker.OnSourcePropertyChanged(Object o, String propName)
at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType)
at System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(Object sender, PropertyChangedEventArgs args)
at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
at MVVMSeaCores.Controls.HelpTip.NotifyOfPropertyChange(String propertyName) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 140
at MVVMSeaCores.Controls.HelpTip.set_IsOpen(Boolean value) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 181
at MVVMSeaCores.Controls.HelpTipManager.OpenNext() in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 102
at MVVMSeaCores.Controls.HelpTipManager.AddedToScreen(HelpTip helpTip) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 115
at MVVMSeaCores.Controls.HelpTipManager.HelpTip_PropertyChanged(Object sender, PropertyChangedEventArgs e) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 67
at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
at MVVMSeaCores.Controls.HelpTip.NotifyOfPropertyChange(String propertyName) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 140
at MVVMSeaCores.Controls.HelpTip.set_IsOnscreen(Boolean value) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpTip.cs:line 195
at MVVMSeaCores.Controls.HelpPopup.View1_Loaded(Object sender, RoutedEventArgs e) in D:\Projects\MVVMSeaCores\MVVMSeaCores\Controls\HelpPopup.xaml.cs:line 181
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.BroadcastEventHelper.BroadcastEvent(DependencyObject root, RoutedEvent routedEvent)
at System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(Object root)
at MS.Internal.LoadedOrUnloadedOperation.DoWork()
at System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Interop.HwndTarget.OnResize()
at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
它始终在一行中发生,为属性 IsOpen 引发属性更改事件,但它似乎是随机发生的(有时一切正常!):
private void NotifyOfPropertyChange(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName)); //<-here
}
}
对于上下文,IsOpen 绑定到弹出窗口的 open 属性:
<Popup x:Name="Popup"
DataContext="{Binding HelpTip, ElementName=userControl}"
IsOpen="{Binding IsOpen}"
StaysOpen="True" PopupAnimation="Fade"
AllowsTransparency="True"
Placement="{Binding Placement, ElementName=userControl}">
并且由一个静态类设置,它确保一次只在屏幕上显示一个,使用加载的事件来更新 IsOnscreen 属性和静态管理器类中的此方法:
private static void HelpTip_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
HelpTip helpTip = sender as HelpTip;
if (helpTip != null)
{
//is this on screen or not?
switch (e.PropertyName)
{
case "IsOnscreen":
//Update our onscreen lists and perform related behaviour
if (helpTip.IsOnscreen)
{
AddedToScreen(helpTip);
}
else
{
RemovedFromScreen(helpTip);
}
break;
case "IsOpen":
lock (helpTip.Lock)
{
if (!helpTip.IsOpen)
{
OpenNext();
}
}
break;
}
}
}
OpenNext 选择一个添加到屏幕的帮助提示,并将其设置为使用 IsOpen 打开,这似乎是导致错误的原因。
一开始我以为可能是并发的问题,但是我把所有的线程化和简化的东西都去掉了,现在实际上一切都在主线程上完成了。
我以前从未遇到过通知属性更改失败的情况,而且我不知道可能出了什么问题。看看这个:System.ComponentModel.Win32Exception: The operation completed successfully 它似乎与使用太多句柄有关(但我不确定我是如何达到打开和关闭 6 或 7 个弹出窗口的限制 - 编辑:还使用任务管理器进行了检查,它在崩溃时使用了大约 530 个。)或者使用了太大的图形或太大的缓冲区,我认为我没有这样做,因为这些弹出窗口只是少数几个组件。
【问题讨论】:
-
用windows任务管理器监控你的进程,看看它消耗了多少句柄。
-
没想到这样做。它上升到并保持在 530 左右,偶尔增加到 540 左右。所以似乎不是句柄。
-
好吧,我猜你在复制崩溃之前不会看到多余的句柄。
-
很容易复制。看似随机,但频繁,使其在 530 崩溃