Trace.Assert не нарушает работу и не показывает окно сообщения

У меня есть приложение WPF, в котором я перемещаю данные на холсте. Проблема началась, когда я как урод попробовал перемещать данные мышкой.

Вот последовательность действий:

  • Срабатывает MouseMove на холсте
  • В MouseMove я меняю некоторые данные
  • A Trace.Assert FAILS. Не ломается ни отладчик, ни окно сообщения
  • Срабатывает еще один MouseMove
  • Данные снова изменены
  • Возникает исключение из-за повторного входа в коллекцию. Там отладчик ломается. Окно сообщения Assert никогда не отображалось.

Большая проблема здесь в том, что я могу вернуться к утверждению, но это не данные в момент сбоя утверждения, а измененные данные в конце ... так что в основном я не могу отладить это правильно.

Вот трассировка стека, начиная с первого MouseMove (обратите внимание на ShowMessageBoxAssert и тот факт, что он все еще продолжается ...):

  .Models.FCurve.MoveKey(int keyIndex = 3, double keyTime = 1182.0) Line 199 C#
  .Models.FCurve.KeyTimeChanged(Models.FCurveKey timeChangeKey = {Models.FCurveKey}) Line 186 + 0x2d bytes C#
  .Models.FCurve.AddKeyToArray.AnonymousMethod(object sender = {Models.FCurveKey}, System.EventArgs args = {System.EventArgs}) Line 163 + 0x11 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  .Models.FCurveKey.OnTimeChanged() Line 45 + 0x14 bytes C#
  .Models.FCurveKey..ctor.AnonymousMethod(object sender = {FCurveEditorTestApp.Impl.FCurveKeyImpl}, System.EventArgs args = {System.EventArgs}) Line 18 + 0x8 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  FCurveEditorTestApp.exe!FCurveEditorTestApp.Impl.FCurveKeyImpl.OnTimeChanged() Line 43 + 0x14 bytes C#
  FCurveEditorTestApp.exe!FCurveEditorTestApp.Impl.FCurveKeyImpl.Time.set(double value = 1182.0) Line 34 + 0x8 bytes C#
  .Models.FCurveKey.Time.set(double value = 1182.0) Line 36 + 0x1b bytes C#
  .ViewModels.CurveKeyViewModel.X.set(double value = 1182.0) Line 32 + 0x2b bytes C#
  .ViewModels.CurveAreaViewModel.MoveSelectedItem.AnonymousMethod(ViewModels.CurveKeyViewModel key = {ViewModels.CurveKeyViewModel}) Line 127 + 0x2d bytes C#
  Collections.CollectionHelper.ForEach(System.Collections.Generic.IEnumerable source = {System.Linq.Enumerable.OfTypeIterator}, System.Action action = {Method = {Void b__8(ViewModels.CurveKeyViewModel)}}) Line 31 + 0xe bytes C#
  .ViewModels.CurveAreaViewModel.MoveSelectedItem(double deltaX = 693.0, double deltaY = 35.0) Line 126 + 0x63 bytes C#
  .Views.CurveAreaView._AreaCanvas_MouseMove(object sender = {System.Windows.Controls.Canvas}, System.Windows.Input.MouseEventArgs e = {System.Windows.Input.MouseEventArgs}) Line 195 + 0x2d bytes C#
  PresentationCore.dll!System.Windows.Input.MouseEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) + 0x34 bytes 
  PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x27 bytes 
  PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) + 0x3e bytes 
  PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source = {System.Windows.Controls.Canvas}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseEventArgs}, bool reRaised = false) + 0x1bf bytes 
  PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender = {System.Windows.Controls.Canvas}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseEventArgs}) + 0x79 bytes 
  PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseEventArgs}, bool trusted) + 0x35 bytes 
  PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() + 0x311 bytes 
  PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) + 0x42 bytes 
  PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) + 0x62 bytes 
  PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) + 0x2e2 bytes 
  PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd = 2628604, int msg = 512, System.IntPtr wParam = 1, System.IntPtr lParam = 30409804, ref bool handled = false) + 0x22b bytes 
  PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd = 2628604, int msg = 512, System.IntPtr wParam = 1, System.IntPtr lParam = 30409804, ref bool handled = false) + 0x75 bytes 
  WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd = 2628604, int msg = 512, System.IntPtr wParam = 1, System.IntPtr lParam = 30409804, ref bool handled = false) + 0xbe bytes 
  WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7a bytes 
  WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback = {Method = {System.Object DispatcherCallbackOperation(System.Object)}}, object args = {MS.Win32.HwndSubclass.DispatcherOperationCallbackParameter}, bool isSingleParameter = true) + 0x8a bytes 
  WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler = null) + 0x4a bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x44 bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, bool isSingleParameter) + 0x91 bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority priority, System.Delegate method, object arg) + 0x40 bytes 
  WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd = 2628604, int msg = 512, System.IntPtr wParam = 1, System.IntPtr lParam = 30409804) + 0xdc bytes 
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  System.dll!System.Diagnostics.AssertWrapper.ShowMessageBoxAssert(string stackTrace, string message, string detailMessage) + 0x103 bytes 
  System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message, string detailMessage) + 0xb2 bytes 
  System.dll!System.Diagnostics.DefaultTraceListener.Fail(string message) + 0xa bytes 
  System.dll!System.Diagnostics.TraceInternal.Fail(string message = "") + 0xb6 bytes 
  System.dll!System.Diagnostics.Trace.Assert(bool condition) + 0x1c bytes 
  .ViewModels.CurvePathViewModel.CurvePathViewModel(Models.FCurveKey startKey = {Models.FCurveKey}, Models.FCurveKey endKey = {Models.FCurveKey}, ViewModels.IInterpolationProvider interpolatorProvider = {ViewModels.InterpolationInfoProvider}) Line 29 + 0x4e bytes C#
  .ViewModels.CurvePathViewModel.CurvePathViewModel(ViewModels.CurveKeyViewModel startKey = {ViewModels.CurveKeyViewModel}, ViewModels.CurveKeyViewModel endKey = {ViewModels.CurveKeyViewModel}, ViewModels.IInterpolationProvider interpolatorProvider = {ViewModels.InterpolationInfoProvider}) Line 20 + 0x81 bytes C#
  .ViewModels.CurveViewModel.UpdateSegmentForKey(ViewModels.CurveKeyViewModel key = {ViewModels.CurveKeyViewModel}) Line 215 + 0x41 bytes C#
  .ViewModels.CurveViewModel.KeyViewModelsChanged(object sender = Count = 13, System.Collections.Specialized.NotifyCollectionChangedEventArgs e = {System.Collections.Specialized.NotifyCollectionChangedEventArgs}) Line 187 + 0x30 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + 0x50 bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedAction action, object item, int index, int oldIndex) + 0x34 bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.MoveItem(int oldIndex, int newIndex) + 0x6f bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.Move(int oldIndex, int newIndex) + 0xe bytes 
  Collections.CollectionSynchronizer._SourceList_CollectionChanged(object sender = Count = 13, System.Collections.Specialized.NotifyCollectionChangedEventArgs e = {System.Collections.Specialized.NotifyCollectionChangedEventArgs}) Line 239 + 0x45 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  WindowsBase.dll!System.Collections.ObjectModel.ReadOnlyObservableCollection.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs args) + 0x1d bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ReadOnlyObservableCollection.HandleCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + 0xe bytes 
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + 0x50 bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedAction action, object item, int index, int oldIndex) + 0x34 bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.MoveItem(int oldIndex, int newIndex) + 0x6f bytes 
  WindowsBase.dll!System.Collections.ObjectModel.ObservableCollection.Move(int oldIndex, int newIndex) + 0xe bytes 
  .Models.FCurve.MoveKey(int keyIndex = 1, double keyTime = 489.0) Line 199 + 0x19 bytes C#
  .Models.FCurve.KeyTimeChanged(Models.FCurveKey timeChangeKey = {Models.FCurveKey}) Line 186 + 0x2d bytes C#
  .Models.FCurve.AddKeyToArray.AnonymousMethod(object sender = {Models.FCurveKey}, System.EventArgs args = {System.EventArgs}) Line 163 + 0x11 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  .Models.FCurveKey.OnTimeChanged() Line 45 + 0x14 bytes C#
  .Models.FCurveKey..ctor.AnonymousMethod(object sender = {FCurveEditorTestApp.Impl.FCurveKeyImpl}, System.EventArgs args = {System.EventArgs}) Line 18 + 0x8 bytes C#
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  FCurveEditorTestApp.exe!FCurveEditorTestApp.Impl.FCurveKeyImpl.OnTimeChanged() Line 43 + 0x14 bytes C#
  FCurveEditorTestApp.exe!FCurveEditorTestApp.Impl.FCurveKeyImpl.Time.set(double value = 489.0) Line 34 + 0x8 bytes C#
  .Models.FCurveKey.Time.set(double value = 489.0) Line 36 + 0x1b bytes C#
  .ViewModels.CurveKeyViewModel.X.set(double value = 489.0) Line 32 + 0x2b bytes C#
  .ViewModels.CurveAreaViewModel.MoveSelectedItem.AnonymousMethod(ViewModels.CurveKeyViewModel key = {ViewModels.CurveKeyViewModel}) Line 127 + 0x2d bytes C#
  Collections.CollectionHelper.ForEach(System.Collections.Generic.IEnumerable source = {System.Linq.Enumerable.OfTypeIterator}, System.Action action = {Method = {Void b__8(ViewModels.CurveKeyViewModel)}}) Line 31 + 0xe bytes C#
  .ViewModels.CurveAreaViewModel.MoveSelectedItem(double deltaX = 82.0, double deltaY = -9.0) Line 126 + 0x63 bytes C#
  Views.CurveAreaView._AreaCanvas_MouseMove(object sender = {System.Windows.Controls.Canvas}, System.Windows.Input.MouseEventArgs e = {System.Windows.Input.MouseEventArgs}) Line 195 + 0x2d bytes C#

Возникает вопрос: почему это могло произойти, и что мне делать, чтобы это сломалось во время Assert?

Я подумал об использовании исключения, может быть, для отладки, но на самом деле это утверждение, которое мне нужно. Я также думаю обо всех своих других утверждениях, без необходимости всегда преобразовывать их в исключения для отладки ...


person FrankyB    schedule 18.11.2009    source источник


Ответы (2)


Вы можете сделать это на основе домена всего приложения (на основе всего приложения, если ваше приложение имеет только один домен приложения), написав свой собственный TraceListener.

Сначала создайте проект библиотеки классов MyTraceListeners.dll, содержащий класс ExceptionTraceListener:

public class ExceptionTraceListener : TraceListener
{
  public override void Write(string message)
  {
    // Do nothing
  }
  public override void Fail(string message)
  {
    Debugger.Break();  // or if you prefer, throw new Exception(...)
  }
  public override void Fail(string message, string detailMessage)
  {
    Debugger.Break();  // or if you prefer, throw new Exception(...)
  }
}

Теперь вы можете зарегистрировать этот TraceListener в .config файле вашего приложения обычным способом:

<configuration>
  ...
  <system.diagnostics>
    ...
    <trace>
      <listeners>
        <clear />
        <add name="myListener" type="ExceptionTraceListener, MyTraceListeners" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Когда вы запускаете свое приложение с этими записями файла .config, отладчик немедленно прекращает работу при каждом неудачном утверждении.

Также обратите внимание на <clear /> в этом файле конфигурации, чтобы очистить все значения по умолчанию TraceListeners, перечисленные в Machine.config. Это важно, потому что по умолчанию TraceListeners примет вызов раньше вашего и все равно будет отображать MessageBox.

person Ray Burns    schedule 19.11.2009

Я видел нечто подобное раньше, обходной путь, который работал в то время, заключался в добавлении оператора if с тем же условием, что и assert, но с отрицанием, в сочетании с точкой останова, установленной в отладчике для оператора в блоке then блока if .

person rsp    schedule 18.11.2009