# Tuesday, August 26, 2008

Nachtrag zur Zwangsheirat: §91 AO

Mit AO ist die Abgabenordnung gemeint, in der die grundlegenden Regelungen für Besteuerungsverfahren verzeichnet sind. In meinem Widerspruch gegen die Zwangsheirat wurde § 91 AO erwähnt. Diesen möchte ich hier kurz nachreichen ;)

§ 91 Anhörung Beteiligter
(1) Bevor ein Verwaltungsakt erlassen wird, der in Rechte eines Beteiligten eingreift, soll diesem Gelegenheit gegeben werden, sich zu den für die Entscheidung erheblichen Tatsachen zu äußern. Dies gilt insbesondere, wenn von dem in der Steuererklärung erklärten Sachverhalt zuungunsten des Steuerpflichtigen wesentlich abgewichen werden soll.
(2) Von der Anhörung kann abgesehen werden, wenn sie nach den Umständen des Einzelfalls nicht geboten ist, insbesondere wenn
1. eine sofortige Entscheidung wegen Gefahr im Verzug oder im öffentlichen Interesse notwendig erscheint,
2. durch die Anhörung die Einhaltung einer für die Entscheidung maßgeblichen Frist in Frage gestellt würde,
3. von den tatsächlichen Angaben eines Beteiligten, die dieser in einem Antrag oder einer Erklärung gemacht hat, nicht zu seinen Ungunsten abgewichen werden soll,
4. die Finanzbehörde eine Allgemeinverfügung oder gleichartige Verwaltungsakte in größerer Zahl oder Verwaltungsakte mit Hilfe automatischer Einrichtungen erlassen will,
5. Maßnahmen in der Vollstreckung getroffen werden sollen.
(3) Eine Anhörung unterbleibt, wenn ihr ein zwingendes öffentliches Interesse
entgegensteht.

Tuesday, August 26, 2008 10:47:36 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback

?? Operator in C#

Wer hätte das gedacht; In der C#-Spezifikation habe ich bereits das ein oder andere Mal herumgestöbert. Dabei ist mir aber glatt der Null-Koaleszenz-Operator ?? durch die Lappen gegangen. Wer ihn noch nicht kennt, sollte ihn sich einmal anschauen. Es lohnt sich auf jeden Fall.

Wo ich es her habe: BlaBlubBlog
Wo es sonst nach was dazu zu lesen gibt: Norbert Eder
Wo man es brauchen kann:
In der nachfolgenden Funktion wird durch den Null-Koaleszenz-Operator sichergestellt, dass die Klasse test in der Methode Main auf jeden Fall ungleich null ist (auf Stil und Schönheit wurde übrigens in diesem Beispiel kein Wert gelegt).
namespace ConsoleApplication1
{
    using System;

    class Program
    {
        static void Main( string[] args )
        {
            TestClass test = TestClass.CreateClass( ) ?? new TestClass( );
        }

        public class TestClass
        {
            public bool IsValid { get; private set; }

            public TestClass( )
            {
            }

            public static TestClass CreateClass( )
            {
                if ( new Random( ).Next( 1 ) == 0 )
                {
                    TestClass result = new TestClass( );
                    result.IsValid = true;
                    return result;
                }
                return null;
            }
        }
    }
}
Tuesday, August 26, 2008 10:09:39 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [2] | Trackback
# Sunday, August 24, 2008

Zwangsheirat

So, der gröbste Umzugsstress ist vorbei und meine Rechner sind auch wieder im Netz. Ich möchte daher den freien Nachmittag nutzen, um eine kleine Geschichte zu erzählen, die mir während der Umzugsvorbereitungen passiert ist. Sie gehört ganz klar in die Kategorie: Was man während der Umzugsvorbereitungen überhaupt nicht gebrauchen kann.

Der erste Brief

Am 09.07.2008 erreichte mich folgender Brief:

Von:
Finanzamt XXX

An:
Herrn Peter Vitt
Frau A B (Name geändert)
Meine Privatadresse

Text:
Sehr geehrter Herr Vitt, sehr geehrte Frau B,
Sie werden künftig bei dem Finanzamt XXX für die Einkommensteuer unter der Steuernummer 123/4567/8910 (bisher 109/8765/4321) geführt.
{Allgemeine Hinweise}

Leider verhält es sich so, dass ich Frau A B überhaupt nicht kenne, geschweige denn, mit ihr verheiratet oder anderweitig liiert bin. Wie kommt das Finanzamt wohl zu der Annahme, uns nun gemeinsam veranlagen zu müssen. Einige Tage später rief ich darauf hin beim Finanzamt an. Der Sachbearbeiter, der sich meldete (seine Nummer stand auf dem Brief) konnte mit der Sache jedoch nichts anfangen und wusste auch nicht, wie seine Nummer wohl auf den Brief gekommen ist.. Er versprach, sich um die Sache zu kümmern.

Der zweite Brief

Als ich zwei Wochen später noch immer nichts vom Finanzamt gehört hatte, verfasste ich einen Brief. Am 21.07.2008 schrieb ich:

Von:
Peter Vitt

An:
Finanzamt XXX

Subject:
Einspruch gegen Zwangsheirat

Text:
Sehr geehrte Damen und Herren,
Hiermit erhebe ich Einspruch gegen die von Ihnen vorgenommene Zwangsheirat von mir, Herrn Peter Vitt, {Geburtsdatum und -ort}, mit Frau A B, weitere Daten unbekannt, welche mir in Ihrem Schreiben vom 09.07.2008 mitgeteilt wurde.

Hinweis: Seit dem 19. Februar 2005 ist Zwangsheirat als "Nötigung zur Eingehung der Ehe" ausdrücklich aks Regelbeispiel für einen besonders schweren Fall der Nötigung gemäß § 240 Abs. 4 Nr 1, 2. Alternative des Strafgesetzbuchs (StGB) strafbar. Die Tat wird mit Freiheitsstrafe von sechs Monaten bis zu fünf Jahren bestraft. Der Tatbestand der 240 StGB lautet auszugsweise:
"(1) Wer einen Menschen rechtswidrig, mit Gewalt oder durch Drohung mit einem empfindlichen Übel zu einer Handlung, Duldung oder Unterlassung nötigt, wird mit Freiheitsstafe bis zu drei Jahren oder mit Geldstrafe bestraft.
...
(4) In besonders schweren Fällen ist die Strafe Freiheitsstrafe von 6 Monaten bis zu fünf Jahren. Ein besonders schwerer Fall liegt in der Regel vor, wenn der Täter
1.eine andere Person zu einer sexuellen Handlung oder zur Eingehung der Ehe nötigt. ..."
Hätten Sie mir Frau B wenigstens vorgestellt; Die Katze im Sack kaufe ich nicht einmal dem Finanzamt ab. Außerdem ist meinen Recherchen nach Frau B Jahrgang 1954. Das entspricht nicht ganz meiner Altersklasse. Sollten Sie also noch einmal auf die Idee einer Zwangsheirat kommen, bitte ich Sie, die Auswahl zielgruppengerecht durchzuführen und den beteiligten Parteien ein Mitspracherecht einzuräumen. Und Singles eignen sich im Übrigen besser für solche Vorhaben. Sie können sich nicht vorstellen, wie meine wirkliche Partnerin auf diese Nachricht reagiert hat.

Zurück zur Sache: Ich möchte darum bitten, dass die Zusammenveranlagung unter der Steuernummer 123/4567/8910 rückgängig gemacht wird und ich wieder allein unter meiner bisherigen Steuernummer 109/8765/4321 geführt werden. Des Weiteren möchte ich darum bitten, meine Lohnsteuererklärung, die Anfang Juni 2008 unter meinem Namen und der Steuernummer 109/8765/4321 bei Ihnen eingegangen ist, schnellstmöglich zu bearbeiten.

Mit freundlichen Grüßen

Der dritte Brief

Am 24.07.2008 erreichte mich folgende Mitteilung:

Von:
Finanzamt XXX

An:
Herrn Peter Vitt
Meine Privatadresse

Text:
Sehr geehrter Herr Vitt, sehr geehrte Frau B,
Sie werden künftig bei dem Finanzamt XXX für die Einkommensteuer unter der Steuernummer 123/4567/1098 (bisher 123/4567/8910) geführt.
{Allgemeine Hinweise}

Sollte das Finanzamt wirklich so dröge sein?

Der vierte Brief

Am 25.04.2008 erreichte mich dann noch ein Schreiben:

Von:
Finanzamt XXX

An:
Peter Vitt

Subject:
Einspruch gegen Zwangsheirat, Ihr Schreiben v. 21.07.08

Text:
Sehr geehrter Herr Vitt,
Ich möchte mich für Ihren Hinweis bezüglich der von uns durchgeführten Zwangsheirat und die rechtlichen Ausführungen zu dieser Problematik bedanken.
Es tut mir leid, dass wir Sie mit der von uns ausgewählten Partnerin nicht zufriedenstellen konnten. Ich verspreche, dass wir uns zukünftig mit der Auswahl mehr Mühe geben und auch die Betreffenden vorher anhören werden, § 91 AO.

Aufgrund eines Eingabefehlers wurde Ihnen Frau A B als Ehefrau zugeordnet. Ich bitte dieses Versehen zu entschuldigen und hoffe, dass Ihnen hierdurch keine großen Unannehmlichkeiten entstanden sind.

Ihre "Zwangsehe" wurde bereits wieder aufgehoben.

{...alte Steuernummer...neue Steuernummer...Einkommensteuererklärung...veranlagt...}

Mit freundlichen Grüßen

Sunday, August 24, 2008 5:02:09 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback
# Monday, July 28, 2008

Winsock connect immer erfolgreich

Nun, ein seltsames Problem ist mir da über den Weg gelaufen. Letzte Woche ist mein neues Werkzeug angekommen; Ein Laptop soll meine Shuttle-PC ersetzen. Heute habe ich zum ersten Mal die Windows-Version unseres aktuellen Projekts gestartet und dabei ein Verhalten beobachtet, dass mir bereits einige Entwickler aus dem Team berichtet hatten, ich jedoch nicht reproduzieren konnte.

Der Laptop ist mit einem Kabel am Netzwerk angeschlossen. Das Kabel  war vorher an einem i.LON 100 internet server angeschlossen, für den ich ein Netzwerk-Interface programmiert habe. Da dies nun abgeschlossen ist, habe ich dem Server einfach mal das Kabel geklaut und meinen Laptop damit verbunden. Als ich nun die Software angeworfen habe, hat diese auch schön brav die Konfigurationsdatei für das Interface gefunden, die EInstellungen ausgelesen und wollte diese mit dem Server angleichen. Also, Socket aufmachen und Packete tauschen. Was ja nicht funktioniert, da der Server nicht am Netzwerk hängt. Allerdings schlug beim connect() nicht der Timeout zu, sondern es wurde eine korrekte Verbindung gemeldet.

Auf die Schnelle konnte ich im Netz nichts finden, auch eine andere Entwickler hatten dies noch nicht beobachtet. Ich dachte daher, dass es an der geänderten Netzwerkhardware oder dem Treiber liegen müssen. Also habe ich den aktuellsten Treiber installiert; jedoch ohne Erfolg.

Gerade bin ich jedoch auf eine interessante Seite gestoßen: Die winsock Implementierung meldet immer einen erfolgreichen connect, wenn eine Modemverbindung verfügbar ist. Wobei verfügbar nicht mit geöffnet zu verwechseln ist, sondern wenn ein Modem vorhanden ist.

Ich werde also morgen mal im BIOS das Modem des Laptops deaktivieren und dann mal schauen, ob ich noch immer einen erfolgreichen Verbindungsversuch gemeldet bekomme. Für mich als Winsock-Neuling auf jeden Fall ein lehrhafter Tag. Morgen mehr...

Nachtrag 31.07.08:
Es ist nicht ganz beim 29.07. geblieben. Allerdings habe ich mittlerweile einige Test durchgeführt. Weder das Ausschalten des Modems in Gerätemanager noch das Ausschalten des Modems im BIOS hat das Ergebnis de Connect-Methode beeinflusst. Ich werde das ganze noch einige Male beobachten. Vlt. hat ja noch jemand eine Idee? Sollte sich was ergeben, werde ich es natürlich hier bekannt geben.

Monday, July 28, 2008 8:20:13 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback
# Tuesday, July 22, 2008

Spartanisch Programmieren - von Stefan Lieser

Stefan Lieser schreibt in seinem Blog, er wäre ein Freund des spartanischen Programmierens. Ich kann mich ihm dort nicht anschließen, da ich lieber Code schreibe, der sich lesen lässt; Variablen bekommen Namen, die auch ein Außenstehender versteht, Code wird kommentiert, es wird mit Freizeilen zur Strukturierung gearbeitet etc. Aber das ist, wie Stefan bereits schrieb, eine persönliche Einstellung. Wenn sie nicht durch Implementierungskonventionen erzwungen oder verboten wird.

Weshalb ich mich jedoch aufgefordert fühle, auf seinen Blogpost zu antworten, ist sein Fast-Exit-Beispiel. Um eine große Verschachtelungstiefe zu vermeiden, schreibt Stefan lieber viele Exits in einer Funktion, statt seinen Code ordentlich zu strukturieren. Zuerst ein schlechtes Beispiel (von Stefan ebenfalls als schlecht angesehen):
public void DoSomething() {
  if (a) {
    if (b) {
      if (c) {
        DoItRealy();
      }
    }
  }
}

Nun seine Verbesserung (Stichwort Fast-Exit), mit der ich noch immer nicht einverstanden bin:

public void DoSomething() {
  if (!a) {
    return;
  }
  if (!b) {
    return;
  }
  if (!c) {
    return;
  }

  DoItRealy();
}


Und nun zwei Arten, die ich persönlich den beiden Vorangegangenen (nicht uneingeschränkt, aber meistens) vorziehen würde:

public void DoSomething() {
  if ( ( a )
    && ( b )
    && ( c ) )
  {
    DoItRealy();
  }
}

public void DoSomething() {
  if (!a) 
  {
    Log("Not a");
  }
  else if (!b)
  {
    Log("Not b");
  }
  else if (!c)
  {
    Log("Not c");
  }
  else
  {
    Log("All requirements complied.");
    DoItRealy();
  }
}
Tuesday, July 22, 2008 7:01:54 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [1] | Trackback
# Thursday, July 17, 2008

creative commons-Party in Siegen

So, nach langer Zeit nochmal ein Post. Diesmal auch nur, da der Lokalpatriotismus mich dazu treibt ;) Technische Einträge werden auch wieder hier erscheinen, allerdings ist momentan die Zeit einfach etwas zu knapp.

Nun zum eigentlichen Thema: In Siegen findet am 05.09.2008 die erste (Siegens erste) "creative commons"-Party statt. Das 7inch geht auch diesmal wieder in die Vorreiterrolle; dort geht es um 19:00 Uhr los, der Eintritt ist frei (was auch sonst). Wer möchte, kann sich die dort gespielte Musik auf einen mitgebrachten USB-Stick kopieren lassen. Und wer nicht kommen kann, findet neben einigen Informationen auch zwei Live-Streams auf der Seite der Veranstalter.

Falls sich jemand fragt, was eine "creative commons"-Party ist: Creative Commons ist eine Lizenzform, so wie die GPL. Nun gibt es Musiker, die ihre Musik unter einer CC-Lizenz veröffentlichen. Je nach Ausprägung kann diese Musik unterschiedlich verwendet werden (herunterladen und weiterverbreiten, weiterverbreiten nur mit Nennung des Künstlers etc.). Die Beiträge in diesem Blog werden zum Beispiel unter der "CC by-nc-sa"-Lizenz veröffentlicht: Man darf vervielfältigen, veröffentlichen, verbreiten und weiterverarbeiten. Bedingungen: Namensnennung, keine kommerzielle Nutzung, Weitergabe unter gleichen Bedingungen.

Eine "creative commons"-Party nun ist eine Party, bei der nur Musik gespielt wird, die frei erhältlich ist, sozusagen Open-Source-Musik. Daher ist auch die Mitnahme auf USB-Stick möglich.

Thursday, July 17, 2008 12:33:58 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback
# Tuesday, June 24, 2008

InternalsVisibleToAttribute

Ein nettes Fundstück: Ich habe gerade ein wenig mit der Testfunktionalität von VS2008 herumgespielt, um ein paar Änderungen an der Blog-Engine zu testen, da bin ich auf das nette Attribut InternalsVisibleToAttribute gestoßen. Mit diesem Attribut kann man einer Assembly Zugriff auf internal deklarierte Methoden einer anderen Assembly gewähren. Sehr nettes Feature für Unit Tests.

Tuesday, June 24, 2008 11:35:27 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback

Hotlines sind was feines - Die Computer dahinter erst recht

Hotlines sind ein Quell steter Freude. Gestern habe ich versucht, eine DSL-Verfügbarkeitsprüfung durchführen zu lassen, jedoch lieferte die Abfrage im Internet keine Ergebnisse:

Wir können leider nicht überprüfen, ob DSL an Ihrem Anschluss verfügbar ist.

Leider können wir für Ihren Anschluss keine verfügbare DSL-Bandbreite ermitteln. Dies kann mehrere Gründe haben:

  • Sie haben keinen Telekom-Telefonanschluss
  • Ihr Anschluss ist noch nicht in unserer Datenbank erfasst
  • Die DSL-Bandbreite muss manuell gemessen werden
Wir empfehlen Ihnen dennoch das für Sie optimale Komplettpaket. Vor der Freischaltung muss die verfügbare Bandbreite eventuell manuell ermittelt werden.

Neben dieser Anzeige steht die Nummer der Hotline 0800-3355222. Da war es für mich naheliegend, dort anzurufen. Gesagt, getan. Die nette Dame teilte mir aber mit, dass ich die falsche Hotline angerufen habe, ich müsse mich an die Telekom-Standard-Hotline 0800-3301000 wenden. Diese sei aber nicht mehr besetzt. Also habe ich dort vor dreißig Minuten angerufen und gehofft, dass ich noch jemanden erreiche. Sie schien sogar besetzt zu sein, denn nach einem netten Gespräch mit dem Computer war ich auch schon in der Warteschlange. Und wie das so üblich ist in einer Warteschlange, habe ich gewartet. 17 Minuten. Um dann mit dem Kommentar "Alle Plätze sind belegt, versuchen Sie es später noch einmal" aus der Warteschlange gekickt zu werden. Danke, Telekom. Hat euer Computer 17 Minuten gebraucht, um festzustellen, dass ihr viel zu tun habt? Besonders kundenfreundlich ist so etwas ja nicht gerade. Ich denke, ich werde morgen dem T-Punkt einen Besuch abstatten. Dort soll es noch Menschen geben.

Allerdings; Allemal besser als bei GMX. Dort werden Anrufe von unliebsamen Kunden nämlich gar nicht mehr angenommen. Rabiat, aber hilfreich. Kurzfristig jedenfalls. Sollte das gängige Praxis bleiben, wird GMX wahrscheinlich von den Kunden nicht mehr angenommen.

Tuesday, June 24, 2008 9:44:18 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [2] | Trackback
# Monday, June 23, 2008

Multithreading - Teil 2 - System.Threading.Monitor

Im zweiten Teil der unbestimmt langen Reihe Multithreading in .NET befasse ich mich mit der Klasse System.Threading.Monitor.

System.Threading.Monitor

Der Monitor ist das Objekt, was sich bei genauerer Betrachtung hinter einem lock-Statement verbirgt. Die Details dazu können im ersten Teil nachgelesen werden. Die Verwendung ist der eines lock-Statements sehr ähnlich. Man verwendet den Monitor stets in Verbindung mit einem Objekt, welches verriegelt werden soll. Der daraus resultierende IL-Code unterscheidet sich ebenfalls nicht von dem eines lock-Statements.
private void monitorNotationExample( object lockObject )
{
    Monitor.Enter( lockObject );

    //Critical Section: Do something

    Monitor.Exit( lockObject );
}
Nach der Critical Section muss allerdings im Gegensatz zum lock-Statement die Verriegelung explizit wieder freigegeben werden. Dies macht den Monitor etwas fehleranfälliger als das lock-Statement. Er hat allerdings auch einige ganz entscheidende Vorteile.

Vorteile der Klasse Monitor gegenüber lock

Die Klasse Monitor stellt neben der Funktion Enter noch die Funktion TryEnter bereit, um eine exklusive Sperre für eine Critical Section zu bekommen. Die Funktion TryEnter ist doppelt überladen und liefert jeweils einen Booleschen Wert zurück.

Monitor.TryEnter

Der Aufruf der Funktion Monitor.TryEnter(Object) versucht, eine exklusive Sperre auf das übergebene Objekt zu erlangen. Schlägt dies fehl, weil bereits ein anderer Thread eine Sperre auf dieses Objekt hält, liefert die Funktion ein false zurück. Konnte die Sperre erlangt werden, wird true zurückgegeben.

Monitor.TryEnter (Object, Int32)

Die erste Überladung der Funktion mit dem zusätzlichen Parameter vom Typ Int32 dient dazu, einen Timeout anzugeben. Dieser Timeout wird Anzahl der Millisekunden übergeben, die maximal versucht werden soll, eine exklusive Sperre für das Objekt zu erlangen. Wird zu einem beliebigen Zeitpunkt innerhalb der Zeitspanne die Sperre erlangt, gibt der Aufruf true zurück. Wird der Timeout erreicht, kehrt der Aufruf mit false zurück. Dieser Aufruf ermöglicht es also, eine bestimmte Zeit auf eine Sperre zu warten. Der Rückgabewert muss also in jedem Fall ausgewertet werden. Außerdem muss man bei der Verwendung der Funktion Monitor.TryEnter (Object, Int32) darauf achten, dass eine geeignete Strategie vorhanden ist für den Fall, dass keine Sperre registriert werden konnte.

Monitor.TryEnter (Object, TimeSpan)

Die zweite Überladung verlangt als zweiten Parameter keinen Int32, der die Anzahl der Millisekunden für den Timeout angibt, sondern eine Zeitspanne vom Typ System.TimeSpan. Mit dieser zweiten Überladung ist es also möglich, die ersten beiden Funktionsaufrufe nachzubilden. Entweder wird als Zeitspanne wirklich eine Zeitspanne übergeben, was der ersten Überladung entspräche, oder es wird Timeout.Infinite übergeben, was dem Aufruf der Funktion Monitor.TryEnter(Object) entspräche.

Einige Beispiele

Um die Funktionsweise der einzelnen Methoden der Monitor-Klasse zu verdeutlichen, werde ich einige Beispiele anführen. Beginnen wir mit einfacheren Verwendung des Monitors. Wir nehmen einen Konsolenanwendung und erweitern diese mit der Klasse AsyncTest. In dieser Klasse sind zwei Methoden enthalten, Sync1() und Sync2(). Beide Methoden greifen auf dasselbe lock-Objekt zu. nämlich lock1.
class Program
{
    static void Main( string[] args )
    {
        AsyncTest test = new AsyncTest( );
        Thread thread1 = new Thread( new ThreadStart( test.Sync1 ) );
        Thread thread2 = new Thread( new ThreadStart( test.Sync2 ) );

        thread1.Start( );
        thread2.Start( );
        Console.ReadLine( );
    }
}

public class AsyncTest
{
    private object lock1 = new object( );

    public void Sync1( )
    {
        Monitor.Enter(lock1);
        for ( int i = 1; i <= 20; i++ )
        {
            Console.Write( "1 {0}|", i );
            Thread.Sleep( 20 );
        }
        Monitor.Exit( lock1 );
    }

    public void Sync2( )
    {
        Monitor.Enter( lock1 );
        for ( int i = 1; i <= 20; i++ )
        {
            Console.Write( "2 {0}|", i );
            Thread.Sleep( 20 );
        }
        Monitor.Exit( lock1 );
    }
}
Die Ausgabe der beiden Threads erfolgt sequenziell, wie bereits im ersten Teil erklärt.



Schauen wir uns im nächsten Beispiel die Funktionsweise der Methode TryEnter an. Thread 2 in der Main-Routine führt nun die Methode Sync3 in der Klasse AsyncTest aus. Diese versucht über den Aufruf von Monitor.TryEnter(lock1) eine Sperre auf das Objekt zu bekommen.
class Program
{
     static void Main( string[] args )
     {
         AsyncTest test = new AsyncTest( );
         Thread thread1 = new Thread( new ThreadStart( test.Sync1 ) );
         Thread thread2 = new Thread( new ThreadStart( test.Sync3 ) );

         thread1.Start( );
         thread2.Start( );
         Console.ReadLine( );
     }
}

public class AsyncTest
{
    private object lock1 = new object( );

    public void Sync1( )
    {
        Monitor.Enter(lock1);
        for ( int i = 1; i <= 20; i++ )
        {
            Console.Write( "1 {0}|", i );
            Thread.Sleep( 20 );
        }
        Monitor.Exit( lock1 );
    }


    public void Sync3( )
    {
        if ( Monitor.TryEnter( lock1 ) )
        {
            Console.WriteLine( Environment.NewLine + "Lock achieved." );
            Monitor.Exit( lock1 );
        }
        else
        {
            Console.WriteLine( Environment.NewLine + "Lock cannot be achieved." );
        }
    }
}
Ergibt:



Die Ausgabe zu diesem Beispiel entspricht der Beschreibung der Methode Monitor.TryEnter(). Es wird versucht, eine Sperre auf das übergebene Objekt zu registrieren. Schlägt dies fehl, kehrt die Methode mit false zurück. Hätte eine Sperre registriert werden können, wäre true zurückgegeben worden.
Betrachten wir das Verhalten der Methode Sync3() nun einmal mit Übergabe eines Timeouts. Dieser soll 100 Millisekunden lang sein. Die neue Methode nennen wir Sync4() und verdrahten sie in der Main-Methode auf den zweiten Thread:
public void Sync4( )
{
    if ( Monitor.TryEnter( lock1, 100 ) )
    {
        Console.WriteLine( Environment.NewLine + "Lock achieved." );
        Monitor.Exit( lock1 );

    }
    else
    {
        Console.WriteLine( Environment.NewLine + "Lock cannot be achieved." );
    }
}



Wie man sehen kann, kehrt die Methode Sync4 etwas später zurück als Sync3 im vorigen Beispiel, kann jedoch immer noch keine Sperre registrieren. Betrachten wir die Funktion Sync1 genauer, wird auch schnell klar, warum. Sie dauert bei 20 Schleifendurchläufen mit jeweils einem Sleep von 20 Millisekunden mindestens 400 Millisekunden.
Setzen wir nun also den Timeout in Sync4 auf 1000 Millisekunden.



Wie man sehen kann, war der Timeout nun so lang, dass Sync1 vollständig abgearbeitet und die Sperre freigegeben werden konnte, bevor der Timeout abgelaufen war. Der zweite Thread konnte seine Sperre erfolgreich registrieren.

Platzierung der lock-Freigabe Monitor.Exit()

Wie man an Hand der Funktionen Sync3 und Sync4 erkennen kann, habe ich die Freigabe der Sperre nicht an das Ende der Funktion gestellt, sondern an das Ende des Zweigs, der bei erfolgreicher Registrierung der Sperre angesprungen wird. Wird nämlich die Funktion Exit(object) auf ein Objekt aufgerufen, für welches der aufrufende Thread keine Sperre registriert hat, bekommt man von der Runtime eine SynchronizationLockException vor den Bug geknallt, die man dann behandeln darf.
 


Um dies zu vermeiden (und um logischeren Code zu schreiben) sollte man allerdings den von mir gewählten Weg gehen und die Sperre nur dann freigeben, wenn sie auch wirklich registriert wurde. Außerdem sollte man die Freigabe der Sperre in einem finally-Block notieren, um auf alles vorbereitet zu sein. Auch wenn irgendwo innerhalb der Critical Section eine Exception geworfen wird, wird so wenigstens die Sperre freigegeben und die Chance erhöht, dass sich die Anwendung nicht in einem "Deadlock "aufhängt".
Die richtige Notation für den Monitor wäre also:
public void Sync6( )
{
    if ( Monitor.TryEnter( lock1, 1000 ) )
    {
        try
        {
            //Critical section
        }
        finally
        {
            Monitor.Exit( lock1 );
        }
    }
    else
    {
        //else-Fall behandeln
    }
}
Und wem bei der Betrachtung dieser Methode das C# Keyword using in den Kopf kommt, der ist ganz nah bei dem, was sich die .NET-Entwickler gedacht haben. Ändert man den Timeout von 1000 Millisekunden auf Timeout.Infinite und lässt den else-Zweig weg, entspricht diese Methode dem lock-Statement. Womit nun der Unterschied zwischen den drei Methoden Enter, TryEnter und Exit des Monitors sowie dem lock-Statement hinreichend beschrieben sein sollte.

Fassen wir noch einmal zusammen:
  • Das lock-Statement wartet, bis es eine Sperre registrieren konnte. Die Freigabe der Sperre erfolg in einem "finally"-Block (die geschweifte Klammer zu des lock-Blocks).
  • Enter versucht eine Sperre zu registrieren und kehrt sofort zurück. Entweder ist die Sperre registriert (Rückgabe true) oder eben nicht (Rückgabe false). Auf jeden Fall muss sich der Programmierer Gedanken im das Exception Handling machen.
  • TryEnter erweitert Enter um die Möglichkeit, einen bestimmten Zeitraum auf eine Sperre zu warten. Entweder wird die Sperre in diesem Zeitraum registriert (Rückgabe true) oder die Zeit läuft ab (Rückgabe false). Auch hier muss der Programmierer sich um das Exception Handling selbst kümmern.
Im nächsten Teil werde ich die restlichen Funktionen der Klasse Monitor beleuchten: Monitor.Wait(), Monitor.Pulse() und Monitor.PulseAll(). Bis dahin freue ich mich auf Feedback und/oder Anregungen.

Monday, June 23, 2008 9:36:36 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback
# Thursday, June 19, 2008

C# XML Documentation

During my nightly coding session working on my gps class library for my smart phone I started to use the xml decomentation tags see and seealso. Later on after the "nightly build" I had several warnings that the compiler could not resolve the types provided inside these tags. But thanks to Alan Dean and his great artivle about XML documentation in C# my usual sleep amount wont be decreased as much as I feared 10 minutes before.

Thursday, June 19, 2008 11:58:44 PM (W. Europe Daylight Time, UTC+02:00) #  Comments [0] | Trackback