Trace.Assert не прерывается и не показывает окно сообщения - PullRequest
3 голосов
/ 18 ноября 2009

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

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

  • Триггер мыши на холсте срабатывает
  • В MouseMove я изменяю некоторые данные
  • A Trace.Assert FAILS. Отладчик не ломается, как и окно сообщения
  • Еще одно движение мыши срабатывает
  • Данные снова изменены
  • Исключение выдается из-за проверки повторного входа в коллекцию. Отладчик ломается там. Окно сообщения 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#

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

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

Ответы [ 2 ]

5 голосов
/ 19 ноября 2009

Вы можете сделать это на уровне AppDomain (на уровне Application, если у вашего приложения только один AppDomain), написав свой 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. Это важно, потому что по умолчанию TraceListener s будет принимать вызов до вашего и все еще всплывает MessageBox.

0 голосов
/ 18 ноября 2009

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

...