Übersetzungen dieser Seite:

Tipps und Tricks

Hier finden Sie verschiedene Tipps und Tricks rund um C#, .NET und Visual Studio (Verschieden Versionen).

ContextSwitchDeadlock erkennen und umgehen

Fehlermeldung

Message
ContextSwitchDeadlock wurde erkannt. Message: Die CLR konnte 60 Sekunden lang keinen Übergang vom COM-Kontext 0x2c32f90 zum COM-Kontext 0x2c331e0 durchführen. Der Thread, der Besitzer des Zielkontexts/-apartments ist, wartet entweder, ohne Meldungen zu verschieben, oder verarbeitet eine äußerst lang dauernde Operation, ohne Windows-Meldungen zu verschieben. Eine solche Situation beeinträchtigt in der Regel die Leistung und kann sogar dazu führen, dass die Anwendung nicht mehr reagiert oder die Speicherauslastung immer weiter zunimmt. Zur Vermeidung dieses Problems sollten alle STA-Threads (Singlethread-Apartment) primitive Typen verwenden, die beim Warten Meldungen verschieben (z.B. CoWaitForMultipleHandles), und bei lange dauernden Operationen generell Meldungen verschieben.

Diese trit beim abfragen von Fenstertitelnder Anwendungen auf, der Code dazu:

  1. public string Text
  2. {
  3. get
  4. {
  5. try
  6. {
  7. StringBuilder title = new StringBuilder(260, 260);
  8. UnManagedMethods.GetWindowText(this.hWnd, title, title.Capacity);
  9. return title.ToString();
  10. }
  11. catch{return "";}
  12. }
  13. }
  14. private class UnManagedMethods
  15. {
  16. [DllImport("user32", CharSet = CharSet.Auto)]
  17. public extern static int GetWindowText(IntPtr hWnd, StringBuilder lpString, int cch);
  18. ...
  19. }

Der code wird in Visual Studio 2019 im Debug Modus ausgeführt. Wie kann man dieses „hängen bleiben“ erkennen und abbrechen, gibt es da überhaupt eine Möglichkeit?

Erklärung

Wenn man im Debug Modus anhält, dann werden auch keine Windows-Nachrichten mehr verarbeitet. Das heißt, die COM-Komponente verarbeitet eine Windows-Nachricht, die verursacht, dass in deinen Code gesprungen wird. Sollte dann binnen 60 Sekunden keine Rückantwort kommen, dann erhälst Du diese Fehlermeldung, weil die COM Komponente keine weiteren Nachrichten verarbeiten kann derweil.

Lösung

Einfach die Exception in den Visual Studio Einstellungen abschalten.


In Visual Studio 2019 zusätzliche Debug Informationen auschalten

Zusätzliche Debug Informationen

Die Standardeinstellungen in Visual Studio 2019 zeigt oben auf jedem WPF Fenster zusätziche Tool zum debugen des Programm an. Nachteil ist, dass damit auch darunterliegende Komponenten verdeckt werden. Mit folgenden Schritten lässt sich das auch ausschalten:

English Version : Tools → Options → Debugging → General → Enable UI Debugging Tools for XAML Deutsche Version : Extras → Optionen → Debugging → Allgemein → UI-Debugtool für XAML aktivieren

Setzen oder entfernen Sie einfach das Häckchen.


Window und Screen Mouse Koordinaten ermitteln

Wie wir alle wissen gibt es Methoden die uns die Mausposition relativ zu anderen controls zurückgibt. Doch manchmal möchte wir auch die Mausposition ausserhalb des Fensters wissen. Diese Kurzanleitung soll einen kleinen Tipp sein.

  1. #Mit folgenden zwei Methoden lässt sich die Mausposition relativ zu einem control ermitteln:
  2. Mouse.GetPosition(IInputElement relativeTo)
  3. MouseEventArgs.GetPosition(IInputElement relativeTo).

Demo Code

Bei diesem Beispiel wird die Mausposition auf der obersten Titelleiste (WindowTitle) angezeigt. Die Koordination sind innerhalb des Fensters auf die Zeichnungsfläche bezogen und ausserhalb des Fensters werden die Screen Koordinaten angezeigt.

  1. namespace CoreLoader.Views
  2.  
  3.  
  4. {
  5. /// <summary>
  6. /// Interaction logic for Main.xaml
  7. /// </summary>
  8. public partial class Main : Window
  9. {
  10. public Main(object datacontex)
  11. {
  12. InitializeComponent();
  13. DataContext = datacontex;
  14.  
  15. CompositionTarget.Rendering += OnRendering;
  16. }
  17.  
  18. private void OnRendering(object sender, EventArgs e)
  19. {
  20. var x = Mouse.GetPosition(this).X;
  21. var y = Mouse.GetPosition(this).Y;
  22. this.Title = Math.Round(y, 0).ToString() + " | " + Math.Round(x, 0).ToString();
  23. }
  24. }
  25. }

Der Event OnRendering() wird vor dem Zeichnen des WPF Fenster ausgeführt. Dieses Beispiel ist eine verkürzte Abschrift und wurde zur Sicherung kopiert.


WPF, DependencyProperty.Register() or .RegisterAttached

I assume you meant DependencyProperty.Register and DependencyProperty.RegisterAttached.

DependencyProperty.Register is used to register normal DependencyProperty. You can see those as just regular properties, with the added twist that they can take part in WPF's DataBinding, animations etc. In fact, they are exposed as normal property (with the get and set accessors) on top of the untyped DependencyObject.SetValue / GetValue. You declare those as part of your type.

Attached properties on the other hand are different. They are meant as an extensibility system. If you have ever used Extenders in Windows Forms, they are kind of similar. You declare them as part of a type, to be used on another type.

They are used a lot for layout-related information. For example, Canvas needs Left/Top coordinates, Grid needs a Row and a Column, DockPanel needs a Dock information etc. It would be a mess if all of this had to be declared on every Control that can be layouted. So they are declared on the corresponding panel, but used on any Control.

You can use the same thing to attach any information to a DependencyObject if you need to. It can come in handy to just declare a piece of information that you can set in xaml just to be used later in a style for an existing class for example.

So those two kind of DependencyProperty serve a very different purpose. Regular properties (registered through Register() ) are used just like normal properties as part of the interface of your type. Attached properties (registered through RegisterAttached() ) are used as an extensibility point on existing classes.

Hope that clarifies it a bit.

--Denis Troller