Laden...

Forenbeiträge von cadi Ingesamt 308 Beiträge

07.06.2006 - 19:39 Uhr

Hallo S.H.-Teichhof,

ein paar Dinge (nebst des Splitters 😉)

  1. Auch wenn du die Einstellungen in "Eigene Dateien" ablegst finde ich ein Passwort im Klartex extrem unschön.

  2. ein Thread/Posting Datum wäre toll.

  3. Was für eine lustige ungarische Notation benutzt du?
    Variable +"_"+TypeSuffix?
    Habe ich so noch nicht gesehen? Wo kommt das her? Eigene idee?

  4. Die idee Logik und GUI zu trennen finde ich klasse. Alledings sollte das Warten_Form dann auch in die GUI ;

  5. Ok, dass ist sehr persönlich: Deutsche Funktions- und Variablennamen machen mich nervös. Vorallem, wenn dann da Umlaute auftauchen.
    Ich habe mal in Schweden gearbeitet. Ist toll, wenn da ein Ultrahonk ein 'û' oder 'ú' in einer Funktion benutzt. Musste immer Charmap aufmachen oder sonstwoher kopieren um die Sonderzeichen zu bekommen. Die sind auf einer deutschen Tastatur einfach nicht drauf.
    Andersrum hätte ich die auch ziemlich genervt, wenn ich angefangen hätte Variablen "Zähler" zu nennen....
    Insgesamt stört es allerdings auch meine Lesefluß im Source. C# ist dann doch eher englisch als Deutsch.... (aber das ist, wie gesagt, mein Problem)

07.06.2006 - 14:25 Uhr

soetwas in der Art müsste gehen:
x = Random(0-10000)
rückgabe = 100-Wurzel(x)

07.06.2006 - 11:57 Uhr

@.unreal: wir reden über Dateien, nicht Strings im Speicher!
Im übrigen wird auch bei string.Replace nix im orignal String ersetzt. Auch da wird eine Kopie angelegt ... (strings sind sogar komplett immutable. nur mit einem StringBuilder würde da irgendetwas gehen)

07.06.2006 - 11:47 Uhr

Moin motoermaik,

ersetzen kannst du nur, wenn die länge des Ersatzes identisch zur Länge des zu ersetzenden ist.
Mann kann in eine Datei nicht einfügen. (d.h. nicht auf File ebene (ok, wenn man anfängt low-level im NTFS oder FAT rumzuwühlen mag das möglich sein, aber diese Möglichkeit würde ich mal ignorieren wollen) . Mann muss halt alles ab der dersetzung dann selber wieder in die Datei schreiben. Bei langen dateien kommst du da evtl. nicht um eine Tem-Datei rum...)

07.06.2006 - 09:41 Uhr

Hallo schrotty,

Die Performance würde ich für vergleichbar halten.
Aber es gibt eine Menge anderer Faktoren die entscheidend sein können:

  1. Desktop- oder Server-Applikation
    Auf dem Desktop würde ich immer Firebird bevorzugen, da die installation sehr viel schlanker als die der MSDE (immerhin 70MB alleine das Setup) ist. Für den User sind die spezifischen features eher uninteressant.
    Bei einer Serverinstallation ende ich meistens bei einem SQL-Server oder der MSDE. Vorallem, wenn in der bestehenden Infrastruktur bereits SQL-Server vorhanden sind. Damit hat man den Vorteil, das die vorhandenen (DB-) Admins sich um Backups und die Pflege der Datenbank kümmern können (bei "exoten" wie Firebird bleibt das Risiko sonst häfig beim Hersteller der Software. Das kann sehr unscön werden)

  2. Benötigte Features
    Firebird hat eigentlich alles, was man braucht - bis hin zur Möglichkeit es um eigenen Funktionen zu erweitern.
    Der SQL-Server (2005) hat aber so schöne Dinge wie den Reporting-Server und ebenfalls Möglichkeit eigene Funktionen einzubinden (per .NET), das aber viel einfacher als bei Firebird.

  3. SQL-Dialekt
    Die meisten SQL-RDBMS unterstützen zwar ANSI-SQL aber die Syntax von Stored-Procedures und speziellen Typen kann sehr nervig sein, wenn man von einem System auf ein anderes umsteigt.
    Wenn mann z.B. von MS-SQL auf Firebird umsteigt wird man erstmal einige zeit googlen um autoinkremetielle Felder definieren zu können.
    Wenn man von MySQL auf Oracle umsteig wird mann im ersten Projekt wohl kaum PL/SQL soweit beherrschen, das man eine schöne Lösung hinbekommt. Erfahrungen müssen halt auch gemacht werden.

  4. GUI Tools
    MS-Sql hat geniale Tools zum Verwalten und Entwickeln von Datenbanken (Ein debugger für Stored Procedures ist schon was geniales).
    Auch wenn es für MySQL, Oracle, Firebird etc. ähnlich gute Tools gibt, kosten die, die einen wirklich helfen ordentlich Geld. Wenn man allerdings damit leben kann alle seine Tabellen in plain SQL zu erstellen kann man das vernachlässigen (aber erfahrungsgemäß spart ein visuelles Tool da schon eine Menge Zeit)

  5. Kosten
    Das sind zum einen die Lizenzkoste, dann die Kosten für Entwicklertools und letztlich auch die Wartungskosten. In rechnenzentren kann es durchaus sein, das das Hosten von Datenbanken unterschiedlic teuer ist (oder garnicht unterstützt wird und der kunde/entwicklier sich selbst drum kümmern muss)
    Ausserdem kann es teuer werden, wenn man mehr performance braucht und CPUs nachrüsten muss oder ähnliches. (Lizenz pro CPU war mal sehr beliebt)

Fazit:
Mit RDBMS ist es wie mit Programmiersprachen: Es gibt nicht DIE BESTE, sondern nur die BESTE FÜR DEN JOB.
Und das ist eine komplexe Entscheidung. Wenn Geld keine Rolle spielt und der Kunde keinen Ideologischen Probleme mit Microsoft hat (wird er wohl nicht, da wir hier in einen C#-Forum sind) würde ich wahrscheinlich MS-SQL bevorzugen.
Trotzdem Plane ich gerade ein (Desktop-)Projekt mit Firebird 😉

06.06.2006 - 13:04 Uhr

Hi Martin,

Ok, da du evtl. in eine Sackgasse laufen kannst musst du eine art undo machen.
Du willst das also quasi wie ein Labyrinth durchlaufen, oder? immer zur letzten korrekten kreuzung zurück und dann alternativen testen?

Kling für mich nach einem Stack....

PS: Schau dir das mal an: Sudoku Solver and Generator

06.06.2006 - 12:46 Uhr

Hi,

warum muss deine rekursive Funktion denn mit Wertetypen arbeiten?
Willst du den Parameter als CONST übergeben, d.h. unveränderlich?

Struct hilft dir auch nur bedingt, da die List ja als Referenz innerhalb der Struct übergeben wird.

Evtl. hilft ja eine Parameterübergabe von einem kopiertem Object ( Clone() )?

06.06.2006 - 10:43 Uhr

Auch wenn das jetzt nicht direkt etwas mit deinem Problem zu tun hat:
Microsoft empfiehlt ausdrücklich Word NICHT aus einer Webanwendung heraus zu automatisieren! (ich finde den link auf den Knowledgebase-Eintrag leider gerade nicht)

Evtl. solltest du darüber nachdenken die Dokumente nicht über Word-Automatisierung sondern nativ zu erzeugen (Office XML oder 3rd Party Komponenten (syncfusion hat das was nettees). Das hat auch den Vorteil, das auf dem Web-Server kein Office installiert werden muss. Ich glaube auch, das hätte lizenzteschnische Probleme, da der der Webservice wie "Unlimited Users" gezählt wird....

06.06.2006 - 10:35 Uhr

Noch eine kleine Information zu FB.

Es gibt eine embedded Version für .NET.
Embedded heisst, keine Installation. Einfach ein paar Dateien ins Bin-Verzeichnis kopieren und mann hat eine vollständiges Datenbanksystem.

FB ist auf jeden Fall besser als MySQL (PostgreSQL und Informix und eigentlich fast jedes andere RDBMS).
Auch wenn es für MySQL mehr grafische Tools geben sollte, ist die Leistung von FB deutlich besser. IBExpert ist wirklich ein gutes Tool.

18.05.2006 - 15:15 Uhr

@herbivore

Dann ist ja alles klar.
Werde nur noch das MS Muster nutzen (tu ich eh, bei allen klassen, die von einem MS-Disposable abgeleitet sind. Das andere Muster hatt ich mir schon früh angewöhnt... (tja, man kann ja nicht alles wissen... und sowas schleift sich halt ein...)

18.05.2006 - 13:29 Uhr

@herbivore

das kein GC.SupressFinalize rührt daher, das es ja evtl. auch ein (Re-)Open geben könnte. (ok, mann könnte im open auch wieder den Finalizer aktivieren).

Das Pattern von MS / dir ist letztlich doch das selbe in grün, oder?

Das wichtige ist ja nur, das auch bei "falscher" anwendung der klasse (d.h. fehlender Aufruf von Dispose oder ohne using) die resourcen freigegeben werden, oder?

btw:

~MyClass ()
{
   Dispose (false);
}

warum werden im Destruktor die "Unverwalteten Ressourcen" NICHT freigegeben?

18.05.2006 - 11:17 Uhr

Hallo Kostas,

zum Thema IDisponsable und Destruktoren.

Ich habe es mir angewöhnt allen Klasen, die IDisposable implementieren eine Close() funktion zu spendieren.
Dise funktion sollte nur dann was tun, wenn der interne status auf open ist (alse ein aufruf Close auf ein bereits geschlossenens object sollte keine Exception schmeissen. eher ein false zurückliefern)

Die wird dann von der IDisposable.Dispose methode aufgerufen.
In dieser Methode wird dann auch der Destructor Disabled (GC.SupressFinalize).

Im Destruktor wird dann Close() aufgerufen um die resourcen wenigstens dann freizugeben, wenn der GC das objekt Finalized.
Damit kann man sicher sein, das das Objekt - irgendwann zumindest - seine Rresoucen freigibt.

Bsp. (gaaaanz grob):

public class ResourceHolder : IDisposable
{
	private Handle m_SomeWin32Handle;
	public ResourceHolder()
	{	
		// criticla resource! Must be closed!
		this.m_SomeWin32Handle = AquireHandle();
	}
	
	~ResourceHolder()
	{
		// last chance close
		this.Close();
	}
	
	// Close the handle if it is openend
	// returns false if the handle was already closed
	public bool Close()
	{
		if (m_SomeWin32Handle == null)
			return false;
		this.m_SomeWin32Handle.Close();
		this.m_SomeWin32Handle = null;
		return true;
	}
	
	
	public void Dispose()
	{
		// close Handle;
		this.Close();
		
		// make sure Finalizer will not be called...
		GC.SupressFinalize(this);
	}

}
16.05.2006 - 12:53 Uhr

@svenson

Das Problem ist doch, dass die App.Config NICHT jedesmal kopiert werden soll.

Das ist aber doch egal, wenn die App.Config vorher durch die aktuelle ersetzt wird.
(zumindest vom Effekt).
Unschön ist das allemal....

16.05.2006 - 12:02 Uhr

Da hilft wohl nur upgraden oder ein workaround.

Als workaround würde sich evtl. ein BuildEvent anbieten, das die aktuelle Appname.exe.config in das projektverzeichnis als App.config kopiert....

dann ist die App.Config immer aktuell...?

16.05.2006 - 10:15 Uhr

Ehrlich gesagt bin ich schon so lange kein Schüler mehr, das ich da nicht die geringste Ahnung habe.
Das Steuerecht ist in den letzten Jahren auch immer komplizierter geworden und ändert sich immer schneller. Was heute gilt wird morgen (im schlimmsten Fall rückwirkend) wieder geändert.

Aber gibt es für schüler nicht eh irgendwelche Freibeträge?

Ich würde einfach mal einen Steuerberater anrufen. Wenn der für diese Beratung schon Geld will einfach den nächsten anrufen (denke aber bei Schülern sind die nicht ganz zu habgierig... )

Als ich noch Schüler war habe ich das meistens über Sachleistungen gemacht.
D.h. die Firma für die ich arbeite kauft mir am ende einen Schönen Rechner o.ä.
Damals ging das dann komplett an der steuer vorbei und die Firma konnte die anschaffung sogar abschreiben. (wird mit einem Führerschein aber wohl eher schwierig..)

Was ich an deiner Stelle aber auf keinen Fall machen würde ist Schwarzarbeit.
Die Chance, das die Steuer dich prüft ist sehr gering, aber deine Arbeitgeber werden alle eingetragene Gewerbe sein. Früher oder später sind die alle mal fällig.
Und ich kenne fälle wo man wegen einer Rechnung von 10€ mit Polizei und Zoll Durchsuchungen startet... Das Finanzamt ist kein guter Gegner....

16.05.2006 - 10:00 Uhr

Die Frage ist ja eigentlich weniger, ob man ein Gewerbe anmelden muss (das geht extrem einfach und kostet nur ein paar Euro).

Wichtiger ist es, dass man es schafft als Freiberufler annerkannt zu werden. Das spart ordentlich Steuer.
Das sollte man über einen Steuerberater machen. Mit dem sollte man besprechen, wie man seine Arbeit richtig beschreibt, damit das klappt. (bei mir hat es geklappt).

15.05.2006 - 16:19 Uhr

Ich benutze das Grid von Syncfusion.

15.05.2006 - 16:13 Uhr

Hallo Lexodus,

setze doch einfach die das Property "Copy to Output Directory" deiner App.Config auf "Do not Copy" oder "only if newer".

"only if newer" hat den Vorteil, das auch ein clean-build eine App.Config bekommt.

04.05.2006 - 12:48 Uhr

Hallo allesamt,

ich habe folgende Klassenstruktur:


/* ein node = Wort+Annotationen und metainformationen */
public class Node
{
	public string Word {get;set;}
	public string Pos {get;set;}
	//.. und ein paar mehr properties und methoden ..//
}

/* Generische liste von Nodes */
public class NodeList : List<Node>
{
}


/* Eine Phrase */
public class Phrase : List<Node>
{
	/* details omotted for breivity ;) */
}


/*  ein satz bestehend aus nodes und ein paar eigenschaften */
public class Sentence : NodeList
{
	[XmlAttribute]
	[SoapAttribute]
	public string LanguageCode {get;set;}

	public Phrase VerbPhrase {get;set;}
	public Phrase NpPhrase {get;set;}
	public Phrase PpPhrase {get;set;}
}

Meine WebMethod sieht so aus:


[WebService(Description = "Applies POSTagging information to a Sentence", Namespace = "http://xxx.de")]
public class TagSentence : System.Web.Services.WebService
{
	[WebMethod(Description = "Applies Pos-Tag-information to a text", EnableSession = false)]
	public Sentence[] Tag(string source)
	{
	    ILanguageSettings langSettings = Config.ConfigManager.LanguageSettings["de"];
	    Sentence[] result = langSettings.SplitIntoSentences(source);
	    if (result != null)
	    {
	        foreach (Sentence s in result)
	            langSettings.TagSentence(s);
	    }
	    return result;
	}
}

Nun zu meinem Problem:
Der client proxy liefert nicht

Sentence[]

zurück, sondern

Node[][]

Das hat zur Folge, dass auch die Eigenschaften (z.B. LanguageCode oder VerbPhrase) der einzelnen Sätze nicht zugänglich sind.

Ich habe nun herausgefunden, das der XmlSerializer wohl alles Klassen, die ICollection implementieren automatisch zu einem ArrayOfXXX macht (und nur den Indexer serialisiert und alle Properties anscheinend ignoriert).

Leider habe ich nicht heraus gefunden, wie ich das umgehe oder so Anpasse, dass das Ergbnis eine Liste von Sentence wird.

Irgendwer irgendeien Idee, wie ich das hinbekomme? Ich hätte schon gerne alle Eigenschaften zurückgeliefert....

?(

03.05.2006 - 01:12 Uhr

Hall BaumBert,

der compiler meckert, da er ja nicht davon ausgehen kann, dass die while-schleife jemals durchlaufen wird. categorytxt könnte ja leer sein.

das problem kannst du umgehen, wenn du felder auf null initialisierst.

du solltest dann auch vor dem foreach felder auf null testen.

26.04.2006 - 09:39 Uhr

Hi Schattenkanzler,

das wird so nix. Da solltest du einen Error 5 - Access Denied - bekommen.
Um auf den Speicher eines anderen Processes zugreifen zu können muss dein Prozess sich in den Adressspace des zu ändernden Prozesses einklingen (injection).
Dafür gibt es verschiedene Methoden. Ich bevorzuge die über einen Message-Hook.

Btw. Dafür brauchst du dann c++ (oder besser native win32).

24.04.2006 - 11:09 Uhr

Meine erste Tat, nach einer neuen XP-Installation auf einem Laptop, ist immer das Deaktivieren von Clear-Type.

Komischer Weise ist es ja angeblich vor allem für Laptop-/LCD- Bildschirme gedacht.
Aber gerade da finde ich es untertäglich. Mag an meiner Auflösung von 1600x1200 liegen?

Ich persönlich bevorzuge einen "more crispy" Font.

23.04.2006 - 13:05 Uhr

Hallo dr4g0n76,

die Frage ist, was versprichst du dir von 64Bit?
Wenn du viel Haputspeicher linear adressierbar haben willst/musst, dann würde sich der Umstieg lohnen (gerade bei Photoshop).
Aber hat dein Rechner denn mehr als 2GB Ram (bzw. mehr als 4GB)?

21.04.2006 - 21:26 Uhr

hallo BaumBert,
fbembedd ist kein .NET assembly.
D.h. du musst/kannst es nicht in deinem Projekt refenzieren.
Die Dll muss nur später im BIN verzeichnis deiner Applikation liegen.

21.04.2006 - 19:39 Uhr

Hallo BaumBert,

das hängt davon ab, was für Daten du in welcher Menge speicher willst, und was du dann damit machen möchtest.

Da kommt alles von CSV über XML bis hin zum SQL-Server in frage.

Wenn es um das Problem der Verteilung/Installation eines RDBMS geht solltest du dir mal den embedded Firebird anschauen.
Das ist eine freie SQL Datenbank, die ohne Installation auskommt.

21.04.2006 - 16:55 Uhr

Hallo Fabian,

CompileToAssembly can auch in eine Datei compilieren.
Wenn ich mich richtig entsinne musst du nur das CodeBase property vom AssemblyName setzen. Dann kannst du beim starten auf das Vorhandensein der DLL testen und das Assembly entweder laden oder erstellen.

Aber mir stellt sich die Frage, was für Monster Regexes das sein müssen, das das Compilieren in ein Assembly nötig wird.

Nimm doch einfach eine statische Klasse mit statischen Regexes...

19.04.2006 - 20:44 Uhr

Hallo jan223,

wie der SMTP server schon sagt: er will die mail nicht ausliefern, frag deinen Administrator.

Das Problem hat nix mit c# zu tun, sondern nur mit der Konfiguration des SMTP Servers.
Wahrscheinlich versuchst du eine E-mail mit einer Absernderadresse zu versenden, die nicht originär auf dem SMTP Server gehostet wird.

ist aber aus deinen XXXX anyonymisierungen nicht mehr zu erkennen...

19.04.2006 - 14:40 Uhr

@IamTheBug: sorry, muss an deinem nick liegen 😉

19.04.2006 - 13:30 Uhr

Hallo IamTheBug,

du liset ja auch zwei zeilen auf einmal aus...

einmal in der While-Bedingung und und dann direkt danach noch einmal.


while ((line = t.ReadLine()) != null) // <- 1. lesen einer zeile
{
   line = t.ReadLine(); // 2. lesen
..

10.04.2006 - 11:52 Uhr

Hallo sknebel,

was meinst du mit "nach unten verschieben"?
Warum benutzt du nicht Insert?

Zur Breite: Schau mal unter ListView.Colums in der Hilfe...
ColumnHeader.Width sollte doch das sein, was du haeb willst.

10.04.2006 - 11:27 Uhr

Hallo BK01,

bitte nenn das keine "gute alte Funktion" (ist nichtmal eine)

Und BITTE gewöhn dir nicht ein


Try
{
  // code...
} 
catch
{
//ignore
}

Konstrukt an.
Manchmal macht das Sinn, aber nur manchmal.
Du wirst später richtig viel Spaß beim debuggen haben, wenn du einen Fehler in einer Funktion suchst, die nicht macht weil sie soll, weil eine andere Funktion einen undefinierten Zustand hinterlassen hat.

Genau das hat VB einen so schlechten Ruf eingebracht.

07.04.2006 - 16:06 Uhr

Hallo norman_timo,

normalerweise braucht man dann eiene eigene ComFactory, die die objecte aus der DLL instanziert.
Normalerweise macht man das ja über CoInitialize, CoCreateInstance etc.

Man kann - theoretisch - auch direct auf die DLL Exports der COM-Dll's gehen und da dann DllGetClassObject direkt aufrufen.

schau dir mal diesen Artikel an: http://blogs.msdn.com/mikhailarkhipov/archive/2005/04/01/404433.aspx

05.04.2006 - 15:14 Uhr

du überpüfst this.Settings auf InvokeRequired, aber führst Invoke dann für this aus....

Zwar sollten alle Steuerelemente eines Formulars im selben Thread erzeugtworden sein wie das Formular... aber mann weiss ja nie.

Ansonsten handhabe ich solche dinge identisch und bei mir klappt das immer.

31.03.2006 - 10:02 Uhr

Hallo Jörg,

Hast du schon die MessageWindow Klasse in CF angeschauit?

ansonsten würde ich mal etwas googeln.
WM_COPYDATA CF MessageWindow receive etc...

da kommt einiges...

30.03.2006 - 22:09 Uhr

fast..... 8)

30.03.2006 - 20:38 Uhr

Hi Powerslave,

nettes Spielchen...

Sorry, aber ich war so an meine C64-Zeiten erinnert, das ich einfach besch.. musste... (so hab' ich damals Programmieren gelernt.. klingt dämlich, aber Spiele Cheaten war eine schöne Herausforderung und man lernte erst Basic und dann Assembler..)

Nun musst du nur noch rausbekommen, wie ich das wohl hinbekommen habe 😉

Viel Spaß beim Rätseln...

30.03.2006 - 18:59 Uhr

Hallo Jörg,

auf den ersten Blick würde ich die Funktion MsgWaitForMultipleObjects der Win32 API empfehlen.

Denn nur ein auf die Message warten bringt dir nicht viel, wenn du nicht mitbekommst wenn die Java Applikation ohne die Nachricht zu senden beendet wird.

Du müsstest also auf das ProcessHandle und die Nachricht warten.

Das Problem an MsgWaitForMultipleObjects ist nur, das es anscheinend nicht für WindowsCE implementiert ist.

Aber evtl. geht es ja auch ganz anders!?

Wenn z.B. die Ergebnisdatei immer gleich heisst, kannst du ja auch einen FileSystemWatcher nutzen und schauen, ob die Datei auftaucht/geändert wird.

Oder die datei vor dem Start des Prozesses löschen und dann nur auf den Prozess warten und schauen, ob die Datei dann da ist?
Das geht natürlich nur, wenn die Java Applikation während ihrer laufzeit nur einmal eine Dateierzeugt und dann beendet wird.

22.03.2006 - 16:09 Uhr

@progger:
das hatte ich kurz überlegt... aber soviel zeit habe ich leider nicht 😭
dachte es gibt irgendwas wie tabellen oder wenigstens tabs?

ok, der baum sieht besch... aus...

  1. versuch:

Initial:


+-a
| +-b
| |  +-d
| +-c
|  
+-b
| +-d
|   +-c
|
+-c
|
+-d
  +-c

C Weg:


+-a
| +-b
| |  +-d
|  
+-b
| +-d
|
+-d

Hoffe, das geht besser...

22.03.2006 - 11:53 Uhr

Moin Eisbär (Golo?),

da das ja nix ist, das 10.000 mal asugeführ wird, sondern einmal beim Start (denke ich), würde ich versuchen Effizienz im Sinne von "schönen" und übersichtlichen Code umzuseetzen.

Am wichtigsten ist es wahrscheinlich nicht auflösbare Kreuztreferenzen abzufangen etc. Es muss ja mindestens ein Plugin geben, das ohne Referenzen geladen werden kann.

Ich würde da einfach eine Baumstruktur verwenden, in den man die Hierarchie der Plugins schreibt.

Dann sucht man den Root node, der auch gleichzeitig ein leaf ist (keine Abhängigkeiten mehr hat).

Den läd man dann und entfernt alle leafes, die auf dieses Plugin beinhalteten.

Dann nimmt man siich den nächsten Root Vor, der ein Leaf ist etc...

Beispiel:


Plugin	Requires
a	b,c
b	d
c
d	c

Dann sieht der Baum initial so aus:


a
	b
		d
			c
	c
b
	d
		c
c

d
	c

D.h. C ist der einzige Root node ohne children, Laden dann löschen.

Danach sieht der Baum so aus:


a
	b
		d
b
	d
		
d

PS: Wie hätte ich den Baum schöner ins Forum gepostet?

Nun kommt D an die Reihe und dann B und dann A...

So würde ich es zumindest machen....

22.03.2006 - 11:26 Uhr

Hi,

ich habe mal eine funktion geschrieben, die den tatsächlichen Speicherverbrauch eines Objeltes inklusive alle properties berechnen sollte.

Die is nicht perfekt, aber man kann mit den ergebnissen was anfangen.
(zumindest ich konnte damit Design-Schwächen in einer monster klasse finden (die hatte eine menge von Listen als Properties die dann auch wieder listen oder komplexe objekte beinhalten konnten).

hier der Code:

using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;

namespace MemoryTest
{

	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class MemHelper
	{


		public static long GetMemoryConsumption(object o)
		{
			return MemHelper.GetMemoryConsumption(o,null,"Object");
		}

		public static long GetMemoryConsumption(object o, ArrayList countedObjects, string parentName)
		{
			long result = 0;
			if (o != null)
			{
				// System.Console.Out.WriteLine("Checking: "+o.GetType().FullName);
				if (o is String)
				{
					result += ((string)o).Length;
				}
				else
				{
					Type valType =  o.GetType();
					if (valType.IsValueType)
					{
						if (valType.IsEnum)
						{
							
							result += System.Runtime.InteropServices.Marshal.SizeOf(Enum.GetUnderlyingType(valType));
						}
						else
						{
							// Date timeß
							if (o is System.DateTime) 
							{
								// spezial treatment
								result += 8;
							}
							else
							{
								result += System.Runtime.InteropServices.Marshal.SizeOf(o);
							}
						}
					}
					else
					{
						if (o is System.Reflection.Pointer)
							return 16;

						if (countedObjects == null)
							countedObjects = new ArrayList();

						// avoid double counting of referenced objects....
						if (countedObjects.Contains(o))
							return 0;

						

						// size of the instance itself...
						// ... result +=  ??? 

						countedObjects.Add(o);
						FieldInfo[] objectFields=  valType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic  /*| BindingFlags.Static*/);
						foreach(FieldInfo fi in objectFields)
						{
							string currentName = parentName+"."+fi.Name;
							object val = fi.GetValue(o);
							// is an list or array??
							if (valType.IsArray)
							{
								Array ar = (Array)val;
								foreach(object oArr in ar)
									result+=GetMemoryConsumption(oArr,countedObjects,currentName);
							}
								/* else if (val is MemoryStream)
								{
									if (((MemoryStream)val).Is
									result += ((MemoryStream)val).Capacity;
								} */
							else if (val is System.Array)
							{
								System.Array arr = (System.Array)val;
								if (arr.Length > 0)
								{
									Type checkTypeObject = null;
									bool valueTypeArray = true;
									for(int i=0; i < arr.Length;i++)
									{
										object arrVal = arr.GetValue(i) ;
										if (arrVal != null)
										{
											if  (checkTypeObject == null) 
											{
												
												checkTypeObject = arrVal.GetType();
												if (!checkTypeObject.IsValueType)
												{
													valueTypeArray = false;
												}
												break;
											}
										}

									}

									
									if  ( (checkTypeObject != null) &&  (valueTypeArray) )
									{
										// simply use count*sizeof type... 
										result+=arr.Length*System.Runtime.InteropServices.Marshal.SizeOf(checkTypeObject);
									}
									else
									{
										// count each element 
										foreach(object oArr in arr)
											result+=GetMemoryConsumption(oArr,countedObjects,currentName);
									} 
								}
								
							}
							else if (val is IList)
							{
								IList list = (IList)val;
								lock(list.SyncRoot)
								{
									for(int i=0;i< list.Count;i++)
									{
										object oList =list[i];
										result+=GetMemoryConsumption(oList,countedObjects,String.Format("{0}[{1}]",currentName,i));
										i++;
									}
								}
							}
							else if (val is IDictionary)
							{
								IDictionary dict = (IDictionary)val;
								lock(dict.Keys.SyncRoot)
								{
									foreach(object key in dict.Keys)
									{
										result+=GetMemoryConsumption(key,countedObjects,currentName);
										object item = dict[key];
										result+=GetMemoryConsumption(item,countedObjects,String.Format("{0}[{1}]",currentName,key.ToString()));
									}
								}
							}
							else
							{
								result += GetMemoryConsumption(val,countedObjects,currentName);


							}
						}
					}
				}
			}

			return result;
		}
	}
}

Das Ergebnis von MemTest.GetMemoryConsumption(o) ist nicht 100% korrekt aber schon ziemlich genau. Um einen überblick zu bekommen, was so ein objekt an speicher bindet ist es recht interesant.

Ein schöne Erweiterung zum debuggen ist es auch zu schauen, welche objekte IDisposable implementieren und dann im Code prüfen, ob man die auch alle objekte Disposed/Closed etc...

20.03.2006 - 18:10 Uhr

Sprache ist für den Menschen ja auch nur eine Folge von Mustern die er wiedererkennt und interpretiert.

das nur würde ich mal steichen wollen. Denn das interpretieren ist die eigentliche leistung.

Und in der Mustererkennung ist der Mench einen Computer, sei er noch so leistungsfähig, immer noch meilenweit vorraus und ich seh in absehbarer Zukunft nichts was darauf hindeutet, das Computer so leistungsfähig werden.

Nun muss ich ja mal fragen, was du mit Mustererkennung meinst.
Das erkennen von unbekannten Mustern oder das erkennen von neuen Mustern?

Beim erkennen von bekannten Mustern denke ich, das es nicht mehr lange dauert und Computer werden das beherschen. (Teilweise tuen sie das ja schon besser als der Mensch. Oder kannst du Fingerabdrücke unterscheiden?)

Das ist letztlich nur eine Frage von Speicher und MHz.

Aber das Erkennen von neuen, unbekannten Mustern ist eine Aufgabe die doch noch was schwieriger ist. Das ist mehr als reine Statistik...

19.03.2006 - 16:06 Uhr

Hallo Khalid,

Noch eine Idee:
Du machst das MainForm zu einem Singleton und gibst dem MainForm ein statisches Property "Instance" (wird dann im Constructor von MainForm auf this gesetzt) und machst dann die benötigten objekte public.
Dann kann man per "MainForm.Instance.User" darauf zugreifen.

Oder du machst ein Konfigurations-Singleton mit den beiden Objekten.

(ok, das klappt nur in einer Single-Users-Anwendung, aber wenn du schon sagst, das die Objekte im Mainform stehen, gehe ich mal davon aus, das nur ein User zur zeit die Applikation nutzt)

17.03.2006 - 16:47 Uhr

Ich halte den Touring-Test auch für wenig geignet um festzustellen ob eine Maschine intelligent ist.

Man kann aber durchaus damit feststellen ob man einen natürlichsprachlich-menschlischen Dialogautomaten hat.

Ich denke die Kunst dabei ist es den Tester geschickt in den bekannten Wissensdomänen zu halten.
Das machen Menschen ja auch so. Ich vermute mal, es würde euch verstören, wenn mein nächstes Posting zum thema Quantenphysik oder Medizin wäre...

Und das halte ich für machbar. Intelligent ist das aber - nach meiner ganz persönlichen definition - noch lange nicht.

Aber ein Schachcomputer ist auch nicht intelligent, oder?

17.03.2006 - 15:50 Uhr

Ich würde jede Wette eingehen, dass zu unseren Lebzeiten kein System den Turing-Test bestehen wird.

Na, wie alt bist du denn?

Ich sehe da durchaus noch Hoffnung das zu meiner Lebzeit zu erleben.
(am liebsten mit meiner Software! naja, schau'n wer mal...)

16.03.2006 - 10:26 Uhr

Hallo herbivore,

manchmal sieht man ja den Wald vor Bäumen nicht.
Ich war einfah zu blöd!
Ich habe das Objekt einfach mit dem falschen Schlüssel in den WeakReferenc-Cache hinzugefügt.

  
private void InternalAdd(TKeyType key, TValueType value)
{
// ... cache full or memory pressure to high?
..... ommitted ....
                    // check if the last item has only one hit, then replace
                    CacheEntry<TKeyType,TValueType> lastEntry = this.m_EntiresById[this.m_EntiresById.Count - 1];
                    if (lastEntry.Hits == 1)
                    {
                        if (this.m_UseWeakReferenceBuffer)
                        {
                            this.m_WeakReferenceBuffer.Add(key, new WeakReference(lastEntry.Value)); // <--- Da ist der BUG
                            m_GlobalPerformanceCounters.ItemsInWRCache.IncrementBy(1);
......

Tja, ich hätte mal lastEntry.Key nehmen sollen.

Ich hätte doch Maurer werden sollen.....

Der Effekt war auf jeden fall extrem verwirrend, da ich in einem Cache B-Tree Pages speichere. Wenn er die durcheinander würfelt wird das eine lustiger index....

Die katastrophe kam immer dann, wenn er fälschlicher weise Page 0 als anstatt einer andern zurückgeliefert hat. Da sind keine b-Tree nodes drinnen, sonder die Meta-Informationen für den Index....

Auf jeden Fall Danke für deine Hilfe!

15.03.2006 - 21:13 Uhr

Hallo herbivore,

das ganze läuft unter .net 2.0.

Ich habe gerade etwas in der Doku gefunden (nach Reflector auf IsAlive).
GC.KeepAlive...

Das Beispiel zeigt dann auch die probleme, die man auf einer mehrprozessor maschine bekommen kann... und der Testrechner hat zwei (vier virtuelle durch HT)) Prozessoren.

Leider ist der Rechner gerade am Rechnen (das kann er am besten). Ich kann also erst morgen testen ob ich ein GC.KeepAlive an das ENDE(!) meiner Funktion die den WeakReferenceCache ausliest stellen muss.

Testprogramm wird nicht so einfach.... Muss ich mal schauen, ob ich da einen UnitTest ohne die echten daten (ein paar hundert MB) hinbekomme... Hab bisher immer nur getestet, ob die da sauber in der DB ankommen.
Ich hab noch nichteinmal was anderes bisher versucht darin zu speichern 😉

15.03.2006 - 21:01 Uhr

GCHandle(Type) war ein guter Hinweis.

MSDN:

WeakTrackResurrection: This handle type is similar to Weak, but the handle is not zeroed if the object is resurrected during finalization.

Hmm... genau das scheint ja zu passieren. Nach der Finalization wird nicht gezeroed. Aber ich habe WeakTrackResurrection nicht gesetzt!?

Wired? Ob ich da evtl. ein Threading-Problem mit der GC habe? Schon finalized, aber nocht nicht zeroed?
Nee.. kann auch nicht sein, denn:

Weak: This handle type is used to track an object, but allow it to be collected. When an object is collected, the contents of the GCHandle are zeroed. Weak references are zeroed before the finalizer runs, so even if the finalizer resurrects the object, the Weak reference is still zeroed.

d.h. es müsste definitiv null sein, wenn das objekt finalized worden ist!

this is f**ing strange!

nun muss ich erstmal den WeakReferenceCache aus machen... seufz!

15.03.2006 - 20:34 Uhr

Hi,

für ein Projekt benötige ich einen zweistufigen Cache.
Zweistufig in sofern, das der erste Cache level ganz normal alle Objekte die man in ihn reingibt in einem Dictionaray mit key ablegt. (nicht direkt, sondern einen cacheentry mit zusätzlichen Statistiken für das Altern und Hit-Statistik etc.)

Das funktioniert auch klasse, ist aber auch bis dahin nicht so schwer.

Die Objekte sind Wortinformationen (Wortart, Flektionen, Lemma, Stamm etc...)
Da sich die Lemmata (Grundformen) auf Objekte der selben Art beziehen muss sicher gestellt sein, das alle Referenzen auf das Lemma "laufen" auf das selbe Objekt (lief, lauft, laufen..) zeigen und nicht auf unterschiedliche instanzen von "laufen".

Die Wortinformation werden in einer (extrem eigenen und proprietären) datenbank gespeichert und on-demant geladen.
D.h. immer, wenn ein Wort nicht im cache ist wird es neu instanziert.

Nun kann ich aber in dem Cache nicht jedes Wort das jemals im Speicher stand ablegen. Das sind ein paar zu viele.

Meine (ich dachte schlaue) Idee war es, objekte, die aus dem Cache durch Expiration oder Überlauf rausfallen, erstmal in einem zweiten Cache der nur WeakReferences hält zu legen.

Die Idee war, wenn ein objekt nicht im 1. Cache ist im zweiten schauen und dann, wenn vorhanden, checke ob die WeakReference noch "Alive" ist.

Klappte auch eine weile ganz gut, bis ich dann mal einen extrem Stresstest gemacht habe: Der 1. Cache durfte nur noch ein Objekt halten.

Nun zum Problem: Ich bekam aus dem WeakReference Cache VALID targets, die aber auf ein anderes Objekt verwiesen haben.

Durch Tracing habe ich auch rausbekommen, dass das Original Objekt auch tatsächlich finalized worden ist.

Das Phänomen scheint zu sein, das (manchmal?) nach dem Finalize Objekte an der selben stelle im Speicher mit dem selben Type erstellt werden auf die das Target der WeakReference zeigt. Und das scheint dann wieder Valid zu sein.

Das scheint irgendwie was mit der Resurrection von Objekten zu tun zu haben. Ich habe aber keine weiteren Informationen gefunden.

Irgendjemand eine Idee? Was bedeutet dieses TrackResurrection genau?

15.03.2006 - 19:58 Uhr

Hallo herbivore,

die Frage ist ja, was ist denn Verstehen?
Akustisch? Grammatikalisch? Inhaltlich? Oder eben Verstehen im Sinne von Reflektieren und dem Erkennen von Metainhalten und Schlussfolgerungen?

Ich denke viele Menschen können die ersten zwei Verständisse bringen die meisten menschen aud, wenn sie Einstein lesen (sollten). Das Inhaltliche/Faktische verstehen wird schon bei den meisten was schwieriger.

E=m*c² kennt jeder und kann auch rein formal jeder inhaltlich wiedergeben.

Aber die Menschen, die wirklich verstehen, was das bedeutet sind schon rar gesät. Und die Paar die daraus noch neue Dinge ableiten sind wohl eher Perlen - sozusagen schrecklich Intelligent 😉

15.03.2006 - 19:46 Uhr

@herbivore: Ich glaube auch nicht, das ein Bewustsein von nötet ist um zu verstehen. (Waum sollte es nötig sein, das der Computer bewust verstehen muss um zu verstehen.)

Wenn verstehen heisst, eine frei formulierte Frage inhaltlich in ihre bestandteile zu zerlegen und dann zu einer bekannten menge von Fragen einen Match herzustellen ist ja schon möglich (erste versuche hierzu hat das DFKI mit dem VerbMobil gemacht. Da ging es aber um eine recht enge Wissensdomäne: Terminabsprachen.

Aber die eigentliche Herausforderung die KI betreffend ist das abstrahieren und assoziieren.

Das, was den Menschen in seiner Intelligenz so von dem Computer unterscheidet, ist ja, dass er in der Lage ist aus mehreren Informationen völlig neue Antworten zu generieren. Er muss vorher die Antwort nicht kennen. Auch die Frage muss ihm vorher noch nicht gestellt worden sein.

Spannend dabei ist dann ja auch noch, das ein Mensch spontane Einfälle haben kann und neues Wissen quasi erschaffen kann. Durch Vermutungen und Schlussfolgerung. Da spielt ja auch Zufall eine Rolle. Die vrostellung ein Computer denkt sich eine Religion aus um fehlendes wissen schlüssig zuerklären ist schon lustig. Aber wohl doch noch Zukunftsmusik.

Für den Moment nin ich froh deutsche Sätze in ihre Struktur - halbwegs sicher - zerlegen zu können.

Das spannende wird jetzt aus Worten Begriffe und Konzepte zu machen.

Cyc ist zwar sehr nett (ähnlich wie WordNet) aber leider nur in englischer Sprache verfügbar.

Sowas in Deutsch wäre mein Traum!