2015-04-22 12 views
5

Ich habe mit einem Problem gekämpft, das vor kurzem mit einer einfachen Logtofile-Klasse aufgetaucht ist, die ich geschrieben habe.Ändern einer Ortszeichenfolge in const bricht meine Logger-Klasse

Diese Klasse funktionierte bis vor kurzem einwandfrei, als ich bemerkte, dass meine Protokolldatei nicht die erwarteten Daten zeigte. Seltsamerweise hatte ich keine Funktionalität der Klasse geändert. Vergleicht man eine alte, funktionierende Version mit meiner neuen Version, bestand der einzige Unterschied darin, dass einige meiner Felder aus private und readonly gemacht wurden. Außerdem wurde die string path in const geändert. Und zu meiner völligen Verwirrung änderte ich das Problem, das ich hatte, wieder auf readonly.

Also meine Frage ist: Wie in aller Welt ist das möglich? Soweit mir bekannt ist, sollte in dieser Situation funktionell kein Unterschied zwischen readonly und const bestehen.

Beim Debuggen ist die Änderung des Verhaltens erheblich, besonders in der Run() Methode. Was sollte passieren hier ist, dass, sobald Log(queue.Dequeue()); aufgerufen wurde, wird der Thread die lock Anweisung verlassen und durchlaufen die while (isRunning) Schleife erneut. Das scheint ziemlich offensichtlich, oder? Wenn ich jedoch die string path zu const ändere und erneut debugge, wird die Log(queue.Dequeue()); einmal übergeben und eine einzelne Anweisung kann in der Protokolldatei gefunden werden, nach der es einfach nichts anderes mehr macht. Es kommt nicht wieder an while (isRunning) vorbei und es scheint den Block lock (obj) nicht zu verlassen. Der Logger-Thread scheint nach erfolgreichem Aufruf von Log(queue.Dequeue()); einfach einmal herunterzufahren oder zu pausieren.

Das Auslösen der Ausnahme in der Log-Methode macht keinen Unterschied, es werden keine Ausnahmen ausgelöst, da die Protokollierung selbst einwandfrei funktioniert.

Ich sollte erwähnen, dass ich diesen Code mit Unity3D 5 verwende, die Mono verwendet. Aber diese drastische Verhaltensänderung scheint mir bei so einer kleinen Bearbeitung unmöglich. Kann jemand erklären, warum das passiert?

Danke! Hier

+0

Ich dachte, es ist ein bisschen zu viel Code war in der Nachrichtentext zu schreiben, aber in Ordnung, Ich habe es hinzugefügt. – David

+0

Es ist viel besser als eine Verbindung, die verschwinden könnte und Ihre Frage zu einem späteren Zeitpunkt unverständlich macht. Einen Logger zu schreiben ist ein schwieriges Geschäft, das bereits gelöst wurde. Wäre es nicht besser, eine bestehende Lösung wie [nLog] (http://nlog-project.org/) zu verwenden? – spender

+0

Komisch, dass du das erwähnen solltest, ich habe nLog versucht, aber ich habe einige Probleme mit Unity3D 5 bekommen. Um zu wiederholen, mein Logger funktioniert gut, nachdem ich das Problem lokalisiert und behoben habe. Ich verstehe das Problem einfach nicht. – David

Antwort

1

ist der Unterschied:

consts in den Metadaten der Dateien erstellt werden, so dass, wenn Sie Sie Klasse laufen der Wert ist schon da.

Readonly in der Kompilierung initialisiert werden, in Ihrem Fall, heren den Trick, auch wenn man auf dem Weg des Mutex zuerst erklärte dann, initialisiert die Compiler das Mutex-Objekt zuerst, hier ist der Grund:

Ihr erstes statisches Objekt zu initialisiert ist der Logger:

public static readonly TimingLogger Logger = new TimingLogger(); 

Weil Sie der Konstruktor aufgerufen, werden die nicht statische Member initialisiert, Mutex das nächste Mitglied machen initialisiert werden. An diesem Punkt haben Sie den Pfad noch nicht initialisiert, also erstellen Sie Ihr Mutex-Objekt mit den Parametern false und null.

Wenn Sie den gleichen Fehler haben wollen, die Sie haben mit const nur lesbar verwenden, können Sie die Reihenfolge der statischen Parameter Initialisierung erzwingen, einen statischen Konstruktor wie:

static TimingLogger() 
{ 
    path = "C:\\Logs\\TimingLog.txt"; 
    Logger = new TimingLogger(); 
} 

Oder einfach Weg vor Logger setzen.

Wenn Sie nicht den Fehler mit konst haben wollen, nur den Mutex ändern Initialisierung null Parameter verwendet:

private readonly Mutex mutex = new Mutex(false, null);