Mittwoch, 19. Mai 2010

SynchronizationContext.Current == null

Warum ist SynchronizationContext.Current manchmal null?

SynchronizationContext ist eine Klasse, die dabei helfen soll, unabhängig von GUI-Technologien (WPF/WinForms) einen Synchronisierungsmechanismus vom Background-Workerthread zurück zum GUI-Thread zur Verfügung zu stellen (GUI-Thread = der Thread, in dem die GUI-Komponente XY erzeugt wurde).

Möglich dass das hier hilft (dort, wo die oberste GUI-Komponente, sprich Dialog/Window verfügbar ist, also z.B. in deren Konstruktor):
if( SynchronizationContext.Current == null )
SynchronizationContext.SetSynchronizationContext(
new System.Windows.Threading.DispatcherSynchronizationContext( this.Dispatcher )
); // ersetze "this" durch irgendein lebendes GUI-Objekt mit Dispatcher
Bei mir passiert das, wenn ich in einem Unit-Test (NUnit) eine GUI-Komponente öffne (warum sollte man das tun? nicht fragen...). Offensichtlich erzeugt der Testrunner einen neuen Thread für den Testfall (ich benutze die Testrunnerfunktion von Reshaper, aber ich denke Testdriven.NET oder der nunit-Runner macht das genauso). Damit ich dann (WPF-)-GUI-Komponenten aufrufen kann, muß ich die Testfunktion mit [STAThread] markieren (oder ist das schon falsch?).

Dann passiert genau das, dass ich den SynchronizationContext manuell setzen muß, und zwar auf den Dispatcher des obersten Fenster, das in dem Testfall erzeugt wird.

[Update 20.05.]
Ich hatte auch die Situation, dass der SynchronizationContext ein ThreadSynchronizationContext ist und kein DispatcherSynchronizationContext. Für meinen Anwendungsfall (Background-Threads posten ein Ergebnis an den GUI-Thread; was sollte man sonst mit einem SynchronizationContext machen?). Scheint das nicht zu gehen, also muß es sogar so lauten:
if( !(SynchronizationContext.Current is DispatcherSynchronizationContext) )
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext( this.Dispatcher )
);

Sonntag, 16. Mai 2010

Visual Studio: Track Active Item in Solution Explorer

Hilfe! Wo ist meine Datei im aktuellen Solution-Baum?

Aktiviert man diesen Schalter



in den Einstellungen, folgt der Solution Explorer nun immer der aktuellen Datei. Bis es nervt. Es nervt ganz sicher irgendwann. Weder das eine noch das andere macht dauerhaft Sinn. Eigenlich braucht man nur eine Funktion "Finde aktuelle Datei JETZT" (nicht "Dauernd Finden an/aus").

Für Anwender von RESHARPER: Resharper/Tools/Locate in Solution Explorer (Shift-Alt-L)

Shift-Alt-L :-) Ich liebe es jetzt schon! Mehr wollte ich ja gar nicht. Alle Nicht-Regesharpten können sich immer noch das Kommando zur obigen Einstellung ("View/Track Item View" glaube ich) als Toolbar-Button irgendwo hin legen. Wenn man dann zweimal draufhaut (Tracking einschalten und gleich wieder ausschalten) erreicht man denselben Effekt wie mit der Resharper-Funktion

;-)

Montag, 10. Mai 2010

C#: LINQ und IEnumerable (non-generic)

Immer wieder falle ich darauf rein:
Da hat man eine Collection of Irgendwas, die man mal schnell mit einer Mengeoperation durchackern will, z.B. durchsuchen oder filtern. Zum Glück gibt's seit .NET 3.5 ja die tollen Extension Methods von LINQ. Also, simsalabim:
using System.Linq;
Und... nichts passiert :( . Intellisense zeigt mir trotzdem keine der Erweiterungsmethoden an. Warum? Tja... Da hat man es wohl mit einem Relikt aus den .NET 1.1-Zeiten zu tun, wie etwa CodeTypeMemberCollection oder DataColumnCollection. Diese Kameraden implementieren nur IEnumerable statt IEnumerable<>. Und ohne Typsicherheit keine typisierte Abfragerei, so einfach. Da hilft (beim ersten Mal hab ich echt lang danach gesucht) die Cast-Methode (die bekommen auch die untypisierten IEnumerables verpasst:

CodeTypeDeclaration type;
...
..
var member = type.Members.Cast<CodeTypeMember>().FirstOrDefault( t => t.Name == name );

Et voilà!

Donnerstag, 6. Mai 2010

MultiTargeting im Visual Studio 2010

Hurra*, endlich umsteigen!

Visual Studio 2010 unterstützt Multitargeting, das heißt man kann sich aussuchen, für welchen .NET Framework einzelne Projekte übersetzt werden. Das wären 2.0, 3.0, 3.5, 3.5 Client Profile und 4.0, also im Endeffekt 2.0er-Runtime oder 4.0er-Runtime, der Rest ist nur Beschränkung der verwendbaren Assemblies.

Für die C#/VB-Assemblies kein Problem.

Wir haben leider gemischte Solutions, wo auch noch ein Haufen alter C++-Kram drin ist (managed/unmanaged gemischt). Nach der Migration steht dort als unterstützter .NET-Framework "4.0" drin, und zwar fix!

Und das ist die Lösung. Es geht nur 4.0! Mit manuellen Änderungen am Projektfile ist es möglich, Visual Studio 2010 dazu zu bewegen, mithilfe des C++-Compilers eines parallel installiert Visual Studio 2008 SP1 auch Assemblies zu erzeugen die sich mit < 4.0 vertragen (! GEHT'S NOCH?? !)

Ich glaub ich muß jetzt erstmal heimgehen...

*) Wieviel "hurra" oder nicht (sh. oben), das steht auf einem anderen Blatt, gehen wir einfach mal davon aus, ich will jetzt unbedingt VS2010, weil es viel besser ist als VS2008

Dienstag, 4. Mai 2010

Shutdown abbrechen

Schon mal auf einem Server gearbeitet und unabsichtlich einen Shutdown/Restart ausgelöst?



Oops! Und jetzt?
"Der Shutdown wird in 5 min ausgeführt. Sie haben folgende Möglichkeiten: -"

Jetzt schon mal losgehen, und für die Kollegen einen Kasten Bier besorgen? Geht auch einfacher: Mit

shutdown -a



in der Kommandozeile ist der Spuk vorbei (*uff* :))