Tipps & Tricks: VS-2010 Hilfe aufbohren

Microsoft ist es wirklich gelungen in zwei großen Schritten die VisualStudio Online Hilfe bzw. MSDN Integration von einem brauchbaren Tool in VC6, über VS-2003/5/8 wo es gerade auszuhalten war, in VS-2010 zu einem Ding zu verwandeln, bei dem mir fast die Worte fehlen.
Man schmeiße alle Funktionen des Hilfe-Viewers weg und behalte gerade die F1-Taste… alle Vorteile, die mir als Vorteile verkauft werden (keine separate Installation, alles im gewohnten Browser etc. siehe Video unten), sehe ich nicht als Vorteile gegenüber den Nachteilen, die in Kauf genommen wurden.
Ein vielleicht hartes Urteil, aber es geht seit Jahren in dieser Beziehung leider nur bergab.
– Just my 2 cents – 🙁

Das Erste was ich sofort vermisst habe war in der folgenden Reihenfolge:

  1. Dynamic Help
  2. Table of contents (TOC)
  3. Sync to TOC
  4. Index
  5. Filter
  6. Direkte Suche in VS, oder dem entsprechenden Viewer

Ich bin dann auf im Internet auf die Suche gegangen und wurde mit 2 Tools fündig, die einem hier helfen können:

HelpViewerKeywordIndex

Aber wie angekündigt soll es auch hier Verbesserungen geben. Und das außerhalb der Wartungszyklen des VS (siehe Video unten mit Ryan Linton). Zumindest was den Index betrifft und die Suchmöglichkeit innerhalb von VS betrifft schafft ein kleines Tool von Ryan Linton (wie versprochen seit dem 20.04.) wenigstens etwas Abhilfe, der HelpViewerKeywordIndex.

Mit diesem Tool erhält man zumindest mal wieder den Index und ein Suchfenster in VS.
Auch dass das Sucherergebnis in einen VS-Fenster angezeigt werden kann ist nett. Leider betrifft diese Einstellung nicht die Funktion der F1-Taste. In diesem Fall wird immer noch der externe Browser angeworfen und nicht der interne, oder ich habe die Einstellung nicht gefunden wo man mit der F1-Taste ein Browser Fenster in VS öffnet.
Ganz verstanden habe ich auch die Option „Display TOC in page“ nicht.
Das Tool ist zumindest mal ein kleiner Schimmer eines eventuellen zukünftigen Lichtblicks 😉

Aber wer weiß, vielleicht lässt Version 1.1 von  HelpViewerKeywordIndex nicht lange auf sich warten.

H3Viewer

Mit H3Viewer, von meinem MVP-Kollegen Rob Chandler, bekommt man zumindest mal wieder das, was man in VS-2008 auch hatte. Table of Contents, Sync to contents. Und der Viewer ist nicht im Browser. Mit dem Ding lässt sich leben oder zumindest ersetzt es den Viewer den wir aus VS-2005/8 kannten ziemlich gut. Und ja, es gibt auch hier wieder Bookmarks, die jetzt keine Favoriten Einträge im Browser sein müssen 😉
Besonders gefreut habe ich mich auch über die Funktion im Index die Doubletten zum gleichen Stichwort im Index in einem separaten Fenster wieder angezeigt zu bekommen, denn nicht jeder Treffer zu GetWindowtext ist der den ich suche.
Nett auch die TTS Funktion (Text to Speech)
Hier fehlen jetzt eigentlich nur noch die Filter zum vollständigen Glück.

Aber wer weiß, was Microsoft uns demnächst noch zu bieten hat. Laut der Homepage von H3Viewer hat Microsoft noch bereits einige andere Viewer in der Schublade.

Siehe auch:
http://channel9.msdn.com/posts/kmcgrath/Help-30-New-Help-System-in-Visual-Studio-2010/

Links:
http://visualstudiogallery.msdn.microsoft.com/en-us/4af86641-a302-4edf-9853-007bcc670b30
http://mshcmigrate.helpmvp.com/viewer

SELECT … FROM … WHERE … NOT IN (…) Mystik

Wieder mal ein ganz normaler Wahnsinn, der einen Stunden gekostet hat…

Wenn wir uns die nachfolgenden SQL Statements ansehen, dann würde ich davon ausgehen, dass die ersten 6 eine Ausgabe erzeugen.

SELECT 'Test 1' WHERE 1 IN (NULL, 1, 2, 3, 4)
SELECT 'Test 2' WHERE 1 IN (1, 2, 3, 4)
SELECT 'Test 3' WHERE 1 NOT IN (NULL, 2, 3, 4) -- !!!
SELECT 'Test 4' WHERE 1 NOT IN (2, 3, 4)
SELECT 'Test 5' WHERE NOT (1 IN (NULL, 2, 3, 4)) -- !!!
SELECT 'Test 6' WHERE NOT (1 IN (2, 3, 4))
-- Empty as expected
SELECT 'Test 5' WHERE 1 IN (NULL, 2, 3, 4)
SELECT 'Test 6' WHERE 1 IN (2, 3, 4)

Aber ❗ Pustekuchen ❗
Die Zeilen 3 und 5 erzeugen keine Ausgabe ❗Dadurch, dass in dem Ausdruck in der Klammer NULL enthalten ist funktioniert der NOT IN Test nicht mehr korrekt.

Ich bin darauf gestoßen, weil ich ein Subquery durchgeführthabe und mit NOT IN prüfen wollte, dass ein bestimmter Wert eben nicht in diesem Subquery enthalten ist. Einziges Problem war, dass in einigen Fällen dieser Subquery eben auch NULL als Ergebnis geliefert hat. 
Und genau in diesem Fall funktionierte die Abfrage nicht korrekt (s.o.). Das sah vereinfacht in etwas so aus:

SELECT [ID] FROM [Table1]
    WHERE [SomeData] NOT IN
        (SELECT [OtherIDWithNULL] FROM [Table2])

Ich habe den Subquery dann entsprechende um ein WHERE … IS NOT NULL erweitert und siehe da es ging:

SELECT [ID] FROM [Table1]
    WHERE [SomeData] NOT IN
        (SELECT [OtherIDWithNULL] FROM [Table2]
            WHERE [OtherIDWithNULL] IS NOT NULL)

Rein gefühlt ist das für mich ein Bug, aber es ist keiner ❗
Hier kommt eine Einstellung zum tragen, die sich ANSI_NULL schimpft. (siehe SET ANSI_NULL { ON | OFF })

ANSI_NULL ist im Allgemeinen ON, und das bedeutet, dass ein Vergleich eines Wertes mit NULL immer undefiniert ist. Das ein IN-Statement aber nichts anderes ist als ein Vergleich der einzelnen Werte in der Klammer mit dem Zielwert, führt dies hier zu einem irritierenden Ergebnis. NULL=NULL und 1=NULL ist eben undefiniert und nicht False wenn ANSI_NULL ON ist! Also können die Zeilen 3+5 kein korrektes Ergebnis liefern.
Man beachte: Dies hat keinen Einfluß solange man IN verwendet und nicht NOT IN!

Meine rein persönliche Meinung:
Ich habe selten solch einen Unsinn in einem ANSI-Standard gesehen. Einfach Unlogisch ❗
Für mich ist NULL=NULL und NULL<>AnyThingElse eben True… Just my 2 cents…

Jetzt könnte man meinen, dass es also auch eine Lösung wäre SET_ANSI_NULL OFF zu verwenden ❗ (BTW: Eine Einstellung die auch als Attribut direkt auf der Datenbank selbst gesetzt werden kann). Aber der folgende Hinweis in der Doku sollte einen zum Umdenken bewegen:

Wichtig:
In einer späteren Version von SQL Server wird ANSI_NULLS immer auf ON festgelegt, und jede Anwendung, die für die Option explizit OFF festlegt, löst einen Fehler aus. Verwenden Sie dieses Feature beim Entwickeln neuer Anwendungen nicht, und planen Sie eine Änderung von Anwendungen, in denen es zurzeit verwendet wird.

Da dies also evtl. Einfluss auf andere Codebereiche haben könnte und zukünftig nicht mehr unterstützt wird habe ich auf diese Nutzung verzichtet und lieber das Subquery abgeändert.

PS: Bitte jetzt nicht darauf hinweisen, dass es auch JOIN gibt. Aufgrund der Komplexität der Abfrage und weil diese auch noch nach bestimmten Bedingungen gebaut wurde, war ein IN mit einem Subquery, der einfachere Weg.

Achtung: Die festen Mapping Modes des GDI basieren nicht auf LOGPIXELSX und LOGPIXELSY!

Jeder der mit Fontgrößen und Darstellungsgrößen herumspielt, oder wer selber in Fenstern zeichnet kennt LOGPIXELSX und LOGPIXELSY, die durch GetDevCaps geliefert werden. Diese Werte dienen auch CFont::CreatePointFont und anderen Funktionen bei der Umrechnung von „realen“ Maßen auf die Devicepoints, die man dann benötigt. Alles kein Hexenwerk und überall im Netz beschrieben.
Auf diesem Weg kann man mit etwas MulDiv Arithmetik schnell umrechnen wie viele Punkte man benötigt um etwas von 10mm Größe auf einem Device darzustellen.

Der nachfolgende Code wandelt Einheiten von 1mm entsprechend der Auflösung eines Devices in Pixel um.

pDC->SetMapMode(MM_TEXT);
// Convert mm to with LOGPIXELSX
CSize sizeLogPixel(pDC->GetDeviceCaps(LOGPIXELSX),
            pDC->GetDeviceCaps(LOGPIXELSY));
rect.top = ::MulDiv(rect.top,sizeLogPixel.cy*10,254);
rect.bottom = ::MulDiv(rect.bottom,sizeLogPixel.cy*10,254);
rect.left = ::MulDiv(rect.left,sizeLogPixel.cx*10,254);
rect.right = ::MulDiv(rect.right,sizeLogPixel.cx*10,254);

Die Auflösung von 0,1mm je Einheit ist die Metrik des Mappingmodes MM_LOMETRIC. Man sollte also meinen, dass die Verwendung von MM_LOMETRIC mit einem Faktor 10, der obigen Umrechnung gleich kommt.

pDC->SetMapMode(MM_LOMETRIC);
// Convert mm to 0.1mm
rect.top *= -10;
rect.bottom *= -10;
rect.left *= 10;
rect.right *= 10;

Probiert man dies aus, so stellt man überrascht fest, dass die Größen nicht übereinstimmen.
Der Dokumentation nach müsste man es aber denken.

Mit einem bisschen experimentieren bin ich letztlich auf den Grund gekommen.
Keiner der Mappingmodes MM_LOENGLISH, MM_HIENGLICH, MM_LOMETRIC oder MM_HIMETRIC verwendet LOGPIXELSX oder LOGPIXELSY. Diese Mappingmodes verwenden die Werte HORZRES und VERTRES in dem Viewport-Extent und die Werte HORZSIZE und VERTSIZE im Window-Extent.

D.h. der Viewport-Extent bekommt die Größe des Bildschirmes in Pixeln zugewiesen und das Window-Extent bekommt die Größe des Devices in mm zugewiesen. Nun ist diese Größe (HORZSIZE/VERTSIZE) bei Bildschirmen nicht die reale Größe sondern eine Größe, die der Hersteller festlegt. (Anmerkung: Bei Druckern stimmt dieser Wert)

Nun wäre noch alles OK, wenn sich aus den Werten von VERT/HORZSIZE und VERT/HORZRES nun der Quotient LOGPIXELSX/SY ermitteln ließe. Das ist aber nicht der Fall! LOGPIXELSX/SY sind Skalierungswerte die bei Bildschirmen unabhängig von der realen Auflösung angegeben werden und die z.B. dazu Dienen Schriftgrößen grundsätzlich größer oder kleiner anzeigen zu lassen (siehe auch High DPI Mode).

Die Konsequenz daraus ist, dass die Mappingmodes ein relativ exotisches Einzelleben führen, weil die meisten Entwickler eben korrekterweise auf LOGPIXELSX/SY zurückgreifen. Noch mal sei hier bemerkt, dass für Drucker DCs hier in mir bekannten Fällen kein Unterschied existiert und auch das ist gut so.

Die Lösung die sich anbietet, ist nicht weiter schwierig und sie auch der Grund warum ich erst jetzt auf diesen gesamten Umstand gestoßen bin. Ich habe niemals die MM_LO…/MM_HI… Mappingmodes verwendet. Entweder pur MM_TEXT und wenn ich was anderes benötigt habe einfach MM_ANISOTROPIC, und in der entsprechenden Skalierung habe ich dann meistens die Werte aus LOGPIXELSX/SY verwendet. Also musste es passen.

MM_ANISOTROPIC ist sowieso der Mappingmode der Wahl, wenn es um skalierbare Darstellungen und Zoomfaktoren geht, aber dazu vielleicht mehr in einem Artikel demnächst.

Ich habe ein kleines MFC-Programm gebaut (MappingModeTest), dass diese Konflikte aufzeigt. Ich zeichne dort ein Rechteck auf den Koordinaten 20mm,10mm mit der Größe 60mm,40mm. Damit die verschiedenen Rechtecke alle sichtbar werden verwende ich immer einen Versatz von 1mm und zeichne die Rechtecke in unterschiedlichen Farben.
In der Debugausgabe kann man wunderschön sehen wie Extents mit den Werten aus GetDeviceCaps zusammenhängen.

Dieser Artikel basiert auf zwei Anfragen in microsoft.public.de.vc die dieses unterschiedliche Verhalten aufzeigten und diskutieren:
http://groups.google.de/group/microsoft.public.de.vc/browse_thread/thread/23467a5e95051291/7c66c01b8295eaab
http://groups.google.de/group/microsoft.public.de.vc/browse_thread/thread/201719d23a411256/17b41c09844bf105

VS-2010 steht für MSDN Abonnenten sofort zum Download zur Verfügung

Jetzt wird es ernst 😉
Pünktlich wie angekündigt ist VS-2010 RTM in englisch für MSDN Benutzer verfügbar:
http://msdn.microsoft.com/en-us/subscriptions/downloads/default.aspx?pv=18:370

Die entsprechende Trial Versionen können sofort herunter geladen werden:
http://www.microsoft.com/visualstudio/en-us/download

Auch eine Express Version von VC-2010 ist bereits verfügbar:
http://www.microsoft.com/express/Downloads/

Laut Microsoft sollen Übersetzungen in andere Sprachen noch bis Ende diesen Monates auch zur Verfügung stehen.

Mal einen ganz anderen Blick auf seinen Code werfen mit CppDepend

Vor einiger Zeit habe ich versucht mit einem anderen Werkzeug mal den eigenen Code zu analysieren.
Ich habe CppDepend entdeckt.  http://www.cppdepend.com/

Gerade bei großen Projekten kann man schnell den Überblick verlieren und es ist schwierig die abhängigen Klassen und Objekte in Ihren Verbindungen zu sehen oder mögliche Designprobleme nachträglich festzustellen. Oder den richtigen Ansatzpunkt für Reviews zu finden. Man hat manchmal das Gefühl, dass etwas nicht stimmt, aber man weiß oft nicht genau was.

CppDepend kann helfen schlecht konstruierte Klassen zu finden, Fehler in den Namenskonfentionen oder der Dokumentation und gezielter auf notwendige Reviews hinzuweisen.
Durch eine eigene Abfragesprache ist es extrem einfach große unübersichtliche Funktionen zu finden. Klassen mit zyklischen Abhängigkeiten und extreme Vererbungstiefen aufzuspüren. Besonders einfach wird es zum Beispiel auch Namenskonventionen zu überprüfen. Die eigene Codebase wird durch die Abfragesprache analysierbar.

Ich empfand die graphischen Darstellungen der eigenen Codebasis und die Ergebnisse der Abfragen in diesen Grafiken als extrem anschaulich und nützlich. Weitaus mehr als manche tabellarische Analyse meines Codes.

Einen guten Einblick was hier möglich ist liefern die Case-Studies. Wie zum Beispiel die Analyse der MFC 8.0 (VC-2005) http://www.cppdepend.com/MFC.aspx. Man kann die MFC sicherlich nicht als Glanzstück des OOP bezeichnen, umso mehr ist es mal interessant mit diesem Tool einen Blick auf die MFC zu werfen. Wem das nicht anschaulich genug ist kann sollte sich auch die anderen Case-Studies mal ansehen. Oder noch besser die Software 2 Wochen testen.

Ein gutes Tool, aber leider nicht ganz billig, aber in jedem Fall mal einen Blick wert.

TFSDeleteProject und der Fehler TF30063

Wer nach „TFSDeleteProject TF30063“ googled findet genug Treffer, die eine Lösung anbieten. Viel ist hier nicht mehr dazu zu schreiben.

Hier die für mich wichtigsten Links, für Erklärung und Lösung dieses TFS Problems:
http://blogs.msdn.com/dstfs/archive/2009/08/21/tfsdeleteproject-exe-thwarted-by-windows-sharepoint-services-permissions.aspx
http://vsts-fu.blogspot.com/2008/10/tf30063-you-are-not-authorized-to.html
http://social.msdn.microsoft.com/Forums/en-US/tfsadmin/thread/b5e6a42a-dc22-499c-97e0-4fe5b563d49a/

Der letzte Link beschreibt die Lösung, aber es geht auch etwas schneller ohne sich an die Site und den TFS anzumelden ❗

Wer in die Site-Administration geht wird dort immer den Benutzer TFSSETUP als Site Collection Administrators vorbelegt finden.
Anstatt nun den eigenen Account in die Sharepoint Site Collection Administrators und in die Team Foundation Administrators einzutragen, kann man dem Account TFSSETUP auch die Rechte geben sich lokal an einem beliebigen Rechner anzumelden auf dem VS-2008 installiert ist. Das geht am einfachsten wenn man den TFSSETUP Account in die Gruppe Benutzer/Domänen-Benutzer aufnimmt.
Oft wird dies bei der Installation und dem Anlegen des Accounts nicht einmal eingeschränkt, bzw. der Account ist bereits Domänen-Benutzer 😉
Also als TFSSETUP anmelden und schon läuft der TFSDeleteProject ohne Probleme.

PS: Wenn man es richtig macht nimmt man dem TFSSETUP Account hinterher wieder das Recht für lokales Anmelden, den er benötigt es nicht im Gegensatz zu TFSSERVICE… 😉

Der Visual Studio 2010 Release Candidate ist erschienen

Jetzt geht es in die Schlussphase ❗

Der Release Candidate für VisualStudio 2010 ist nun draußen. MSDN Abonnenten können ihn jetzt schon herunterladen. In den nächsten Tagen wird dann auch ein freier Download zur Verfügung stehen.
http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx

Wie auch schon die Beta 2 gibt es für diesen RC eine Go Live Lizenz, mit der man direkt produktiv entwickeln darf.

Das endgültige Erscheinungsdatum bleibt weiterhin der 12. April 2010

PS: Das jetzt der RC erschienen ist, heißt auch, dass nur noch wirklich extrem gravierende Bugs entfernt werden. Mit dem meisten was wir im RC sehen werden wir wohl auch im fertigen Produkt leben müssen. Ich bin gespannt welche Fehler aus der Beta 2 überlebt haben 😉
Dennoch testen und Fehler melden: https://connect.microsoft.com/VisualStudio?wa=wsignin1.0

Alternative Geldanlage

Seit 2006 Muhammad Yunus für seine Arbeit und seine Grammeen Bank den Friedensnobelpreis bekommen hat, habe ich auch immer mal wieder über Mikrokredite und gerechte Geldanlage nachgedacht.

Durch einen Artikel in der OJC-Zeitschrift Salzkorn bin ich jetzt wieder einmal auf solch eine alternative Bank gestoßen, die Geldanlage nach anderen Maßstäben betreibt:
Oikocredit http://www.oikocredit.org

Ich denke, dass wir uns oft genug hinter dem Gedanken verstecken, dass man alleine nichts machen kann. Aber man kann ❗
Mit 200 Euro, die man für einem Genossenschaftsanteil investiert können viele andere Menschen in dieser Welt, zu gerechten Konditionen, eine neue Perspektive für ihr Leben erhalten.

Also warum nicht auch ein paar Euro investieren bei einer ganz anderen Art von Bank und dabei auch noch immerhin 2% Dividende zu erhalten ❓ Es muss nicht immer eine Spende sein ❗ 😉

Siehe auch http://www.ethische-geld-anlage.de, wen das Thema noch mehr interessiert.

Nachtrag 26.02.2010: Hier der direkte Link zu dem Artikel aus der Zeitschrift Salzkorn http://www.ojc.de/salzkorn/geldanlage-fair-gerecht-dritte-welt-sk4-2009.html

Mein „Baby“ ist nun „Kompatibel mit Windows 7“

Das meine Software auf allem läuft was Windows XP und später heißt war mir schon lange klar 😉 aber ein offizielles „Kompatibel für…“ ist ja schon noch was anderes.
Jetzt habe ich die kostenlose Zertifizierung für die Windows 7 Kompatibilität hinter mich gebracht.
In Klartext ganz offiziell: AG-VIP SQL in der Version 1.20.008 ist kompatibel mit Windows 7

Verglichen mit der Vista Zertifizierung, die wir bei einem 3rd Party Unternehmen (VeriTest) durchgeführt haben, muss ich sagen: Windows 7 kompatibel zu werden ist nicht schwer
Es war wirklich kein großer Aufwand!

Wer sich die Spezifikationen durchgelesen hat wird sehen, dass sich gegenüber der Vista Zertifizierung kaum was geändert hat. Wer also seine Software bereits Vista kompatibel hat, kann gleich einen Durchstart machen und es für Windows 7 auch probieren. Und das schöne: Es kostet nichts!
Ich habe es nicht versucht, aber ich vermute mal, dass genau die Version die ich für Vista eingereicht habe auch durch die Windows 7 Zertifizierung gekommen wäre.

Noch ein paar Anmerkungen:

  • Ich kann jeden ermutigen, den Test zu machen, wenn man sowieso schon ein Code Signing Zertifikat und einen 64bit Rechner zur Verfügung hat. Wenn man auf dem man 64bit Windows 7 virtualisieren kann ist die Zertifizierung wirklich einfach. Ich habe VMWare benutzt und das ist einfach ein super Werkzeug für so etwas.
  • Wie bei vielen Zertifizierungen wird viel zu viel Gewicht auf Installation und Deinstallation gelegt. Das war bei der Vista Zertifizierung auch schon so.
  • Bei der Vista Zertifizierung war noch klar, wie und wo man Waiver (Freistellungen) bekommt, z.B. für Komponenten von Drittherstellern, die Ihre DLLs nicht signieren. Dazu gehört ja auch Microsoft mit den DLLs der MFC 😉
    In diesem Zertifizierungsprozess, erfährt man, dass man sie evtl. benötigt, aber nicht wo man sie bekommt…
  • Manche in meinen Augen wertvolle Tests in der Vista Zertifizierung, wie zum Beispiel, die korrekte Behandlung von Crashes, scheinen vollkommen entfallenzu sein.
  • Der Test bei dem 3rd Party Unternehmen war weitaus tiefer als das was man bei dem Selbsttest macht. Jetzt genügt ja die Software zu starten und wieder zu beenden. Bei den Tests zu Vista sind wir beim ersten mal durchgefallen, weil hier ein Bug in der MFC mit dem Application Verifier gefunden wurde, der uns beim Testen nicht aufgefallen war  (Siehe 1, 2, 3
    Ich empfinde den Selbsttest als zu schwach um dann ein Windows 7 kompatibel Logo zu bekommen.
  • Man muss versichern, dass man keine Spyware zertifiziert oder andere böse Software erzeugt… gelinde gesagt ein Scherz. Bei einem 3rd Party Tester würde solche Spyware (hoffentlich) nicht durchkommen. Das hoffe ich doch wirklich mal! Jetzt muss man nur einen Haken setzen, und sich selbst bestätigen, dass man es nicht tut, obwohl man es evtl. doch tut… 😉
    Das mindert den Wert dieses Logos ungemein.
  • Wenn man früher Geld investierte für eine Zertifizierung, hieß das nicht, dass man deshalb bessere Software produziert. Aber 1000$ waren dennoch eine Schwelle über die nicht jeder Hanswurst mit seiner Mickey-Maus-Software gegangen ist.
    Jetzt bleibt als Schwelle nur noch der Kauf eines Code-Signing Zertifikates bei VeriSign und so was kostet ca. 500$ im Jahr.
  • Ich vermisse schon lange das Verbot anderer Techniken, zum Beispiel ein Verbot von Systemweiten Hooks, wenn man Windows X kompatibel sein will. Wenn dann sollte so etwas auch nur mit einem Waiver und klarer Begründung erlaubt werden.
    Nicht wenige dieser mies programmierten Hooks sorgen für Instabilität, unnützes Aufblähen von Prozessen und manchmal auch miese Performance.

Als Fazit bleibt für mich die Frage:
Was nützt ein Logo, dass man zu leicht bekommen kann?

Es bleibt eine Marketing-Aktion und genauso wurde die Vista und jetzt auch die Windows 7 Zertifizierung auch bei uns in der Firma eingestuft. Technischen Nutzen hat das ganze nicht wirklich.

Was denn nun SwitchToThread(), Sleep(0), Sleep(1)?

Was macht man, wenn man keine Wait-Funktionen verwenden will, aber dennoch möchte, dass ein anderer Thread weiterarbeiten kann. Zum Beispiel, weil man einen Spinlock implementieren will.

Nun es gibt insgesamt vier Methoden die durch das Netz geistern.
Ich gehe mal der Häufigkeit nach, die so in manchen Code-Samples finde:

1. __noop;

Wenn der Lock kurz ist, scheint es das beste zu sein, einfach die Schleife weiterlaufen zu lassen und zu hoffen, dass der ein Thread auf einem anderen Prozessor, die Ressource freigibt. Das eignet sich wirklich nur, wenn die Zeitdauer der Sperre als extrem kurz anzusehen ist und eine hohe Anzahl von Prozessoren zur Verfügung steht.
Nach allen Test, die ich gemacht habe, sollte man aber von dieser Art des Wartens bei einem Spinlock absehen. Es schiebt die Leistung des Kerns auf 100% und bringt nichts.

2.  Sleep(0);

Lies sich gut. Schlafe aber eben nicht lange. Man hat auch schon irgendwo gelesen, dass durch diese Methode der Rest der Zeitscheibe dieses Threads aufgegeben wird und ein anderer Thread an die Reihe kommt.
Leider stimmt das nicht ganz ❗
Liest man die Doku genau steht da aber:

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.

😮 Threads mit höherer oder niedriger Prio haben also nichts davon.

Besonders eklig wird das ganze gerade wenn man Threads unterschiedlicher Prio hat, die hier gegeneinander laufen. Sleep(0); führt in diesem Fall zu einerunnötigen Prozessorlast und eben nicht dazu, dass die Zeitscheibe abgegeben wird. Der Prozess kommt sofort wieder an die Reihe und spin-t weiter.

3. SwitchToThread();

OK. Seit Windows 2000 gibt es diese nette neue Funktion. Damit wird ein anderer Thread aktiv. Egal was für eine Prio er hat. Aber auch diese Funktion tut evtl. nicht genau das was man will.
Auch hier stecken die Tücken im Detail der Doku:

The yield of execution is limited to the processor of the calling thread. The operating system will not switch execution to another processor, even if that processor is idle or is running a thread of lower priority.

Sollte also der Thread, auf den man wartet auf dem anderen Prozessor laufen, so profitiert der nicht von dem Aufruf von SwitchToThread.

4. Sleep(1):

Hiermit erreicht man wirklich was man möchte. Man gibt seine Timeslice auf und erstmal sind die anderen dran.

Mein persönliches Fazit:

Nach meinen Recherchen ist Sleep(1); der vernünftigste Weg seine Zeitscheibe abzugeben. Und nach meinem Dafürhalten ist ein __noop; strickt zu vermeiden. Die Performance ist grottenschlecht.
Das ganze Verhalten hängt extrem auch von den Umständen ab: Zahl der Theads, Häufigkeit der Kollision, Anzahl verfügbare Prozessoren, Verteilung der Prioritäten, Allgemeine Belastung des Systems, Zeitdauer der Sperre etc.

Ich habe mit einigen Parametern gespielt und auch ein kleines Sample gebaut, dass alle 4 oben genannten Funktionen durchprobiert und in dem man auch mit anderen Faktoren (Priorität etc.) spielen kann.
Es zeigte sich, dass Sleep(1); am effektivsten war. Aber dicht auf gefolgt von Sleep(0);, was mich doch etwas überraschte.

Allerdings führen schon kleinste Änderungen (Lockdauer, Zahl der Prozessoren, Spielen mit der Priorität) zu anderen Ergebnissen.
Interessant ist vor allem das Spielen mit den Prioritäten. Man soll nicht glauben, das ein Thread selbst mit niedrigster Prio noch relativ häufig Arbeit bekommt.

Viel Spaß beim Spielen mit dem Code SleepTest