Laden...
Avatar #avatar-2617.png
Benutzerbeschreibung

Forenbeiträge von zommi Ingesamt 1.361 Beiträge

26.01.2011 - 14:41 Uhr

Ram verbrauch mit der ersten Funktion ~35 mb, mit der zweiten Funktion faengt er bei 30 mb an, geht dann bis auf 300 mb hoch, um dann wieder auf 30 mb abzufallen. Sehr merkwuerdig. woran koennte das liegen?

Der .NET Reflector verrät mir, dass die Methoden BitmapSource.Create jeweils ein CachedBitmap erzeugen.

Dieses "cached" intern die Pixeldaten. Dass bedeutet zum einen, dass du unabhängig von dem Quell-Array wirst, und andererseits keine Änderungen am Quell-uchar*-Array mit angezeigt werden.

Da also eh eine Kopie erzeugt wird, verwendet die IntPtr-Variante.

Das Memory-Leak erklärt sich dadurch, dass du wahrscheinlich in deinen Tests viele dieser Bilder erzeugst. Und nach der Verwendung solltest du diese unbedingt mittels Dispose() wieder freigeben! (oder das using-Statement nutzen)
Recherchiere mal wegen IDisposable usw. hier im Forum bzw. bei Google oder msdn.

Rufst du nicht explizit Dispose auf, lebt das Bild solange weiter, bis der GarbageCollector aktiv wird und es abräumt. Bis dahin können sich halt schon 300 MB angesammelt haben.

beste Grüße
zommi

//Nachtrag:

Solltest du (da du anscheinend mehrere Bilder übermittelst) so etwas wie ein Video oder ein aktualisieren eines Bildes benötigen. Also ständig neuer Content, ist diese Variante mit dem CachedBitmap (also BitmapSource.Create) denkbar ungünstig, da jedesmal ein _neues _Bild erzeugt wird.
Willst du wirklich "update", solltest du einmalig ein WriteableBitmap der passenden Größe erzeugen und bei jedem neuen Frame mittels WritePixels die neuen Pixel-Daten rüberkopieren.

26.01.2011 - 14:26 Uhr

Allerdings muss ich jetzt mit /unsafe kompilieren. Geht das irgendwie schoener?

Wenn du auf C# Seite noch den Member "img.data" als uchar* verwendest, dann nicht.
Du müsstest dir von C++-Seite das als Wert anbieten, den du direkt in C# als IntPtr verwenden kannst.

Nutzt du C++/CLI? Dann solltest du einfach eine Methode anbieten, die dir den IntPtr extrahiert. Nutzt du hingegen PInvoke? Dann kannst du einfach Intptr für uchar* einsetzen bei der DllImport-Definition.
Hängt alles ein wenig von deinem Code ab.

beste Grüße
zommi

26.01.2011 - 12:49 Uhr

Hi lutzer,

also verwaltet der C++ Teil die Bilddaten. Auch dafür gibt es eine BitmapSrouce.Create-Methode. Diese erwartet dann einen IntPtr, der auf den (nicht von der .NET CLR verwalteten) Speicher zeigt. Den uchar* kannst du dann in einen IntPtr umwandeln.

Wenn du allerdings die Daten wirklich "abholen" musst, also nicht sichergestellt ist, dass das uchar*-Array so lange lebt, wie du das Bild haben willst, solltest du dir die Daten wirklich erst in ein byte[]-Array umkopieren. Dies wiederum geht mit Marshal.Copy.

beste Grüße
zommi

26.01.2011 - 11:36 Uhr

Hi, wir haben unsere Software auch noch nie obfuskiert. (Industriekunden)

War nicht nötig: Geek and Poke: How To Make A Good Code Review 😉

beste Grüße
zommi

23.01.2011 - 01:01 Uhr

Hallo,

Ich habe sie erweitert und bin zu folgendem Ergebnis gekommen, was meint ihr dazu?

Auch ich finde die Gegenüberstellung teilweise unpassend.

CORBA und WebServices könnte man vergleichen als grundlegende Kommunikations-Middleware/Technologie/Framework (whatever).
Und genauso .NET und JEE. Aber alle untereinander... mhh...bauchschmerzen
Denn schließlich ist .NET eine konkrete Technologie mit Implementierung, J2EE (nur) ein kompletter Plattform Standard, und CORBA sowie WS (nur) Standards für Kommunikations-Middleware.

Irgendwie ist das Birnen mit Äpfeln zu vergleichen. Klar irgendwo ist es alles "Middleware", aber ne direkte tabellarische Übersicht suggeriert eine Vergleichbarkeit die nicht gegeben ist.

CORBA und WS sind Standards, die von den großen Frameworks/Middlewares/Technologien wie .NET oder einer JEE-konformen Implementation, durch gewisse Teilkomponenten implementiert sein können. Schließlich gibt es sowohl für Java als auch für .NET passende Bindings zu CORBA & WS. (als auch proprietäre Eigenlösungen, wie Remoting)

Man könnte höchstens die unterschiedlichen Kommunikations-Middleware Spezifiationen/Implementierungen vergleichen:
CORBA IIOP, Java RMI, .NET Remoing, WebServices, .NET WCF,... Aber selbst das ist kritisch, denn Java RMI ist im Grunde ja nur eine mögliche Implementierung von CORBA IIOP unter Java. Und .NET WCF bietet als komplexere Middleware-Abstraktion die Möglichkeit WebService-Binding als Implementierung zu nutzen.

Richtig gut vergleichbar sind eigentlich nur CORBA und WebServices... 😃

Ich mein, ich kann ja auch nicht zum Thema API folgende 4 Sachen vergleichen: POSIX, Linux, Windows NT und die Standard C Library. (OS-API-Standard, Familie von OSs, konkretes OS, Sprach-API)

Oder aber ein Hardware-Plattform Vergleich zwischen x86, OpenCL, Intel Pentium, FPGA. (Mikroprozessor-Standard, Cross-Hardware-Ptlatform-Framework, CPU Familie, Art von Mikroprozessoren)

Naja, solche Listen könnte man beliebig viele finden 😉

beste Grüße
zommi

14.01.2011 - 12:46 Uhr

Hi nNickSize,

bei mir ist deine Version auch mit 13,8 sekunden noch fast genauso schnell. (selbst im DebugMode mu 15 sekunden noch annehmbar) Und damit vieeel schneller als find mit seinen 2 Minuten. Mhh.. 🤔

Hast du ein anderes "find" als ich ? 😁

beste Grüße
zommi

14.01.2011 - 12:19 Uhr

Hi,

ich vermute mal, dass es sich bei deinen Log-Files um Text-Dateien handelt. Diese in Binär-Blöcke fester Byte-Größe zu zerlegen, macht meines Erachtens wenig Sinn.

Was ist, wenn dein Suchwort gerade auf so eine Blockgrenze fällt? Was ist, wenn du sogar UTF-8 (oder eine sonstige Kodierung mit variabler Zeichenlänge) verwendest und ein Multi-Byte-Zeichen gerade auf eine Block-Grenze fällt? (Der hintere Block ist dann korrupt, da er falsch beginnt. Ein Negativ-Beispiel hierfür liefert leider die msdn selbst bei File.OpenText)

So schön Multithreading auch ist, hier macht es wahrscheinlich mehr Aufwand und Probleme als es nutzt. Vielleicht hast du ja mehrere LogFiles? Oder du kannst den LogFile-Erzeuger dazu bringen, immer nur 1 Million Einträge zu schreiben und dann neue Datei (oder so). Dann könntest du eine Parallelisierung auf Datei-Ebene nutzen - die wäre simpel umzusetzen.

Jedoch bezweifle ich sogar, dass dies etwas bringen würde. Vermutlich ist der Flaschenhals im Endeffekt die IO-Lese-Operation. Und da hilft paralleles Lesen auch nicht.

Insofern solltest du meines erachtens einfach single-threaded arbeiten.

Was etwas bringen könnte, wäre ein asynchrones Einlesen. Das ist so ähnlich, wie das tom-essen andeuten wollte. Aber dafür brauchst du in keinsterweise mehrere Threads. IO-Operationen können ja selbst schon asynchron ausgeführt werden. Und du solltest die Block-Probleme beachten! Und das schön hierfür umzusetzen ist etwas tricky. Ich grübel aber mal drüber nach, wenn mir was schönes eingefallen ist, poste ich es.

So hat man auf 2-CPU-Systemen schonmal was gewonnen. Nur um es nochmal klarzustellen. Der erste Thread würde ausschließlich IO anstoßen und damit die CPU in keinster weise auslasten. Lediglich der zweite Thread lastet einen Core aus. Nur der angesprochene Asynchronizitäts-Effekt könnte etwas bringen. Wenn die Auswertung richtig aufwändig sein sollte (aber das ist sie bei String-Contains nicht) könnte man überlegen, mehrere Auswerte-Threads zu erzeugen. Aber auch da würde ich ab .NET 4.0 einfach

File.ReadLines(...).AsParallel.Where(s => ...)

verwenden und mich nicht um Threading kümmern.

Meine Tests bezüglich C#-einlesens und CommandLine-"Find" sprechen sehr für C#. Mein find-Programm braucht bei einer 1 GB großen Datei 2 minuten. Der C# code nur 13 sekunden:

void FindPerStreamReader(string fileName)
{
    using (FileStream stream = File.OpenRead(fileName))
    using (StreamReader reader = new StreamReader(fileName))
    {
        while (reader.Peek() >= 0)
        {
            var line = reader.ReadLine();
            if (line.Contains(SearchString))
            {
                Console.WriteLine(line);
                //break; // falls du weitersuchen möchtest oder eben nicht
            }
        }
    }
}

Oder aber, zwecks schönerem Code kannst du auch File.ReadLines(...) ab .NET 4.0 verwenden. Ist echt schicker, aber minimal langsamer (16 sek):

void FindPerReadLines(string fileName)
{
    foreach (string line in File.ReadLines(fileName))
    {
        if (line.Contains(SearchString))
        {
            Console.WriteLine(line);
        }
    }
}

Was hast du denn probiert? Warum ist es bei dir so langsam?

beste Grüße
zommi

10.01.2011 - 07:54 Uhr

Hi AKNOT,

deinem Text nach zu urteilen hast du eine 2-Kern-Maschine. Und wenn du mit Verwendung eines BGW nun zu einer fast vollständigen Auslastung kommst, dann arbeitet nicht nur der BGW im Hintergrund fleißig, sondern auch die Anwendung/GUI im Vordergrund ununterbrochen.

Eine mögliche Ursache könnte eine zu häufige Aktualisierung der GUI durch den BGW sein. Ist jetzt nur eine Spekulation, aber rufst du vielleicht nach jedem probiertem Passwort BackgroundWorker.ReportProgress auf? Dann hälst du die GUI nämlich ganzschön auf Trab - das solltest du nur ab und an tun (die GUI ist eh träge, das menschliche Auge langsam, also warum 1000000x pro Sekunde aktualisieren? 1x reicht im Grunde auch 😃

Aber wie unconnected schon geschrieben hat, mit etwas Code könnten wir mehr sagen - das eben war nur Rumgestocherer im Dunkeln.

beste Grüße
zommi

03.01.2011 - 17:24 Uhr

Hi,

für dich ist vielleicht diese Antwort zu "C# Dll config file" auf stackoverflow interessant.

Wenn du dir dies zu Gemüte geführt hast, kannst du gern einen Blick in How to have configuration file for DLL reinwerfen.

beste Grüße
zommi

30.12.2010 - 10:49 Uhr

Hi frankhammer,

was die Benennung angeht, siehe WinAPI - Win32API hat sich einfach eingebürgert, wobei ich fast immer WinAPI als Begriff verwende.

Dass PInvokes prinzipiell böse sind, ist natürlich quatsch. Ein Großteil des .NET-Frameworks tut nichts anderes, als die WinAPI zu kapseln, also die Funktionen per PInvoke aufzurufen, die Parameter "objektorientiert" zu kapseln und die Error-Codes über komfortable Exceptions zu verwalten. (Schau mal mit dem Reflector in die .NET-Framework-Assemblies rein, da wimmelt es von PInvokes)

Natürlich muss man eins beachten: Die Typ-Umwandlung. Die WinAPI (auf C basierend) nutzt das C Typ-System und unter x64 nach dem Schema LLP64.

Beispielsweise SendMessage erwartet HWND, UINT, WPARAM und LPARAM Werte. Nun ist die Frage: Was sind die .NET Äquivalente zu diesen Typen?
Unter x68 kannst du für HWND einfach System.Int32 verwenden und es klappt. (böse) Aber wenn man sich die Windows Data Types näher anschaut, sieht man dass ein HWND ein HANDLE ist und dies ein PVOID. Und nach der LLP64-Konvention sind die unter x86 32 Bit lang und bei x64 eben 64Bit.
Daher ist System.Int32 nicht der platformunabhängig richtige Typ dafür! Stattdessen muss man System.IntPtr nutzen.

Dies ist aber auch oft in den Notes bei PInvoke.net vermerkt, siehe pinvoke: SendMessage.

Neben der Paramter-Achtsamkeit gibt es allerdings keine Schwierigkeiten bei PInvoke zwischen Win64 und Win32.

Außer vielleicht die Tatsache, dass unterschiedliche Windows-Versionen in ihrer API minimal variieren. Aber das steht immer in der MSDN bei den Remarks. (Siehe beispielsweise EnumProcessModules, die entweder in der kernel32.dll oder in der psapi.dll liegen, je nach Windows Version)

Auf der anderen Seite sollte man immer wenn möglich auf die .NET-Framework-Version zurückgreifen, wenn es eine gibt. Denn die korrekte Verwendung der WinAPI erfordert auch, dass man den ReturnWert analysiert und mit GetLastError der Fehlercode, gegebenfalls dann in eine Win32Exception kapselt und wirft. Auch müssen Handles wieder korrekt freigegeben werden. (Dafür gibt es zwar .NET-He.per-Klassen wie SafeHandle und deren Ableitungen, aber man muss sich eben drum kümmern) Dennoch ist die korrekte Nutzung der WinAPI eben eine Schwierigkeit der WinAPI selbst, mit der jeder C/C-Entwickler seit Ewigkeiten umgehen muss, und nicht der Technologie PInvoke!
(Wohlgemerkt heißt das nicht, dass alle C/C
Entwickler die WinAPI korrekt verwenden - das tun leider die wenigsten)

Insofern wäre es wohl korrekt zu sagen, dass dein Unternehmen nicht die WinAPI direkt verwenden möchte - aufgrund der Komplexität. (Aber gegen PInvoke kann man nix sagen! Man könnte genauso ein C++/CLI Projekt anlegen und darin die WinAPI in managed Methoden kapseln, die dann aus C# aufrufbar sind - diese Vorgehensweise wäre dann genauso "böse" - da sie eben die komplizierte WinAPI verwendet - obwohl kein PInvoke beteiligt ist.)

beste Grüße
zommi

18.12.2010 - 12:36 Uhr

Hi,

Ich bin derzeit dabei ein Programm zu programmieren, das sehr Rechenintensiv ist. Dann sollte auch der Zugriff effizient erfolgen können. Das ist bei einem jagged Array so. (siehe Hilfe bei Performance (was ist schneller z.B. int[,] oder List<List<int>>))

Das kopieren eines jagged Arrays ist ebenso effizient möglich.

class Feld
{
    public int[][] feld;
    public int breite;

    public Feld(int breite)
    {
        this.breite = breite;
        feld = new int[breite][];
        for (int i = 0; i < breite; i++)
        {
            feld[i] = new int[breite];
        }
    }

    public Feld(Feld f) // Copy Constructor
    {
        this.breite = f.breite;
        feld = new int[breite][];
        for (int i = 0; i < breite; i++)
        {
            feld[i] = new int[breite];
            f.feld[i].CopyTo(feld[i], 0);
        }
    }

    public Feld KopieErstellen()
    {
        return new Feld(this);
    }
}

Du könntest - wenn breite wirklich sehr sehr groß werden könnte - diese schleife sogar parallelisieren.

beste Grüße
zommi

18.12.2010 - 12:16 Uhr

Hi,

wie herbivore schon sagt, ermöglicht die normale Assembly-Suchreihenfolge von .NET keine beliebigen Ordner. Höchstens ApplicationBase-Unterorder mit passenden Probing in der appconfig.

Allerdings kannst du mit dem AssemblyResolveEvent deine Assembly von irgendwo laden - selbst aus dem Speicher (aus komprimierten+verschlüsselten Resource-Dateien oder so).

Du musst nur sicherstellen, dass dein AssemblyResolve-Handler auch vor dem Auflösungsversuch zugewiesen wird!
Eventuell musst du dafür die Main-Methode in eine neue Klasse auslagern, in der in keinster weise auf die externe Assembly und deren Typen zugegriffen wird. Das sollte eigentlich immer funktionieren. Oder sogar noch im Typ-Konstruktor derjenigen Klasse, welche die Main enthält.

Wenn auch das nicht geht - obwohl das ja eigentlich immer gehen sollte 😉 - könntest du als letzte Lösung das AssemblyResolveEvent noch im Module Constructor (module initializer) zuweisen. Dafür musst du aber manuell n bissl IL-Magie betreiben. Denn weder mit C# noch mit CLI/C++ kannst du explizit nen module initializer erzeugen.

beste Grüße
zommi

17.12.2010 - 19:37 Uhr

Hi Flohen,

vielleicht solltest du auch noch schauen, was zu deiner Firma "passt". (Vielleicht sowas wie: "Wenn ihr viel mit .NET gearbeitet habt, bietet sich vielleicht ASP.NET an." Immerhin haben die Programmierer in eurer Firma ja sicherlich eine Arbeitsweise/Paradigma/Verfahren, dass nicht mit jeder beliebigen Sprache/Framework harmoniert - dann wirds schwierig)

Ich kann nur selbst berichten, dass ich gerade in nem RubyOnRails-Projekt beteiligt bin - und es mir überhaupt nicht gefällt. Ich stell mal meinen Frust provizierend dar [meine persönlichen Erfahrungen dar - ohne jedoch damit einen WebFramework-Streit heraufbeschwören zu wollen - das ist lediglich meine Meinung - ich kenne genügend Leute die mit RoR super klarkommen]:*Wozu brauch ich Ruby wenn es Python gibt? Und da gibts mit Django was vergleichbares zu Rails. (ich will keinen Glaubenskrieg entfachen 😄 ) *Ruby 1.8 Code läuft nicht unverändert mit Ruby 1.9, was total nervig ist in gemischten Teams. Außerdem... was soll man verwenden?!?! Ist wahrscheinlich ähnlich nervig wie bei Python2 vs Python3 (ausgereifte Sprachen gefallen mir da besser 😉 ) *Die ganzen Gems bei RoR (Addons) sind ziemlich unausgereift, schlecht dokumentiert und naja ... wie ich finde nicht zufriedenstellend *Bei uns ist das Testing mit Cucumber und RSpec verdammt langsam. Da macht TDD echt keinen Spaß ! (vielleicht machen wir ja was falsch... kA) *Nachdem ich mich mitlerweile mit der MSDN gut zurechtgefunden hab, finde ich die meisten Dokus anderer Sprachen/Frameworks nur noch ":-(" - darunter auch Ruby sowie Rails. *Es kostet verdammt viel Zeit sich da reinzufuchsen... verdammt viel ! (aber das gilt wohl überall und für alles 😉 ) *Und zum Abschluss noch was Positives: Datamapper in Rails 3.0 sind cool und eigentlich ganz gut gut dokumentiert - ahso und Factories statt Fixtures rocken auch... naja "rocken" 😉... aber sonst bereitet es nich so richtig Vergnügen 😉

Ein paar Punkte gelten vielleicht für alle WebFrameworks/Sprachen analog

//Edit:
Aber worauf ich hinauswollte. Als das Projekt anfing, kannte ich RoR nicht. Ich hab im Internet gesucht und gelesen. Und das klang wirklich alles cool und hip und als ob die halbe Welt nun RoR verwendet und liebt.
Insofern haben mir die zahlreichen Internet-Beiträge nicht alles verraten. Und zu mir passt RoR leider nicht - oder ich nicht zu RoR ?
Und sowas sollte irgendwie auch berücksichtigt werden. Ob nun Staitistiken Sprache/Framework XY ganz oben darstellen oder nicht - es bringt nix, wenn man selbst (als Team) mit dieser damit klarkommt.

beste Grüße
zommi

17.12.2010 - 18:15 Uhr

Hi joh.w,

ich sehe bei dem "Stresstest" auch keine Problematik. Ich würd es noch nicht einmal als Stresstest bezeichnen.

Die API wirbt damit, sie sei thread-safe. Nun kannst du mit 2 Threads vielleicht nur schwer nachweisen, dass sie es nicht ist. Aber mit 1000 Threads kannst du leicht nachweisen, dass sie nicht thread-safe ist.

Ob nun 2 oder 1000, eins wäre erbracht: ein Beweis, dass die API nich thread-safe ist!

beste grüße
zommi

13.12.2010 - 11:03 Uhr

Hi Skato,

dein String ist jetzt 128 Bytes (64 chars) lang.

@herbivore
Der MemoryStream ist ja sein Ziel-Stream, in den er alles reinschreiben möchte.

Aber wie herbivore schon sagt: Encoding.GetBytes(...)

Nebenbei, was ist das für ein "komisches" Dateiformat? soll der String nullterminiert sein? Wieso maximale Länge. Wo speicherst du die korrekte-String-Länge, ...

beste Grüße
zommi

13.12.2010 - 00:06 Uhr

Hi lava,

=> Wo bleibt die letzte Zeile, in der der aktuelle Environment-Ordner ausgegeben wird?..
Gebe ich da jetzt "dir" ein, wird plötzlich diese Zeile inkl. meine Eingabe angezeigt. => Wieso?

Mittels

read.ReadLine()

liest du stets nur komplette Zeilen ein. Und ein aktueller Prompt wie

C:\Users\user>

endet eben nicht mit einem Zeilenumbruch.

Du müsstest also den Code so anpassen, dass er einfach alles bisherige liest:

while (!(read.EndOfStream))
{
  Console.Write((char)read.Read());
}

beste Grüße
zommi

12.12.2010 - 22:35 Uhr

Hi dr.gaucho,

hast du eigentlich irgendwo ne richtige Spezifikation der .NET PE-Sektionen gefunden? (Hab grad kurz gegooglet, aber noch nix gefunden)

Aber was mein eigentlicher Ratschlag ist, schau mal bei Mono.Cecil vorbei. Das kann ja auch PE-Files korrekt lesen und die SourceCodes sollten dir helfen.

Interessant ist da vor allem die Mono.Cecil.Metadata/UserStringHeap.cs.

Die verwendet ne Extension-Method ReadCompressedUInt32, die wiederum in der
Mono.Cecil.Metadata/Utilities.cs definiert ist.

Und das schaut sehr vielversprechend aus 😃

Aber eigentlich könntest du auch komplett Mono.Cecil verwenden, dann sparst du dir den ganzen Aufwand 😉

beste Grüße
zommi

12.12.2010 - 15:51 Uhr

Hi dr. gaucho,

ein genauer Blick in die msdn ergibt:1.Die Methode(n) gibts: "Supported in: 4, 3.5, 3.0, 2.0, 1.1, 1.0" 1.Die Methode(n) sind protected, also nur für erbende Klassen sichtbar. Willst du sie also verwenden, musst du zunächst einen eigenen "BinaryReader" davon ableiten, in der du diese Method dann über eine neue öffentlich zugänglich machen kannst.

Aber ich weiß nicht, ob die .NET-Framework implementierung sich absolut mit deiner deckt. Vergleiche mal selbst den Text, der bei der Write-Methode steht.
Aber deshalb sollst du es ja auch ausprobieren 😉

beste Grüße
zommi

11.12.2010 - 14:04 Uhr

Es kommt drauf an, wie du es verändest... aber du könntest ja das MetadataToken der Methodendefinition verwenden.

Oder aber (so mach ich es momentan in einem ähnlichen Projekt) Ich tagge die Methode mit programmatisch mit "[MyMethodId(<id>)]".

beste Grüße
zommi

11.12.2010 - 10:59 Uhr

Hi,

Beim Lesen musst du nicht ständig ein neues Byte-Array blockCopy-en.
Anstatt auf byte[]-Arrays mit BitConverter zu arbeiten, pack um das byte[]-Array lieber einen MemoryStream und um diesen einen BinaryReader. Dann geht das wesentlich komfortabler, du musst dir keinen aktuellen Index/Position merken und liest päckchenweise einfach hintereinander weg !

Beim schreiben solltest du natürlich auch den BinaryWriter verwenden.

So wird aus

UInt16 Paklänge = 10;
byte[] Paklänge_arr = BitConverter.GetBytes(Paklänge);

byte videoIDa = 0x11; //videoID Byte 1 als hex
byte[] videoIDa_arr = BitConverter.GetBytes(videoIDa);

byte videoIDb = 0x11; //videoID Byte 2 als hex
byte[] videoIDb_arr = BitConverter.GetBytes(videoIDb);

UInt32 counter = 1000; //Hole Zählerwert mit 4 Byte
byte[] counter_arr = BitConverter.GetBytes(counter);

Int32 reserve = 11; //4 Byte reserve
byte[] reserve_arr = BitConverter.GetBytes(reserve);
Array.Reverse(reserve_arr);

MemoryStream memStream = new MemoryStream();
memStream.Write(Paklänge_arr, 0, Paklänge_arr.Length);
memStream.Write(videoIDa_arr, 0, 1);
memStream.Write(videoIDb_arr, 0, 1);
memStream.Write(counter_arr, 0, videoIDa_arr.Length);
memStream.Write(reserve_arr, 0, reserve_arr.Length);

byte[] DataPaket = memStream.ToArray();

dann

MemoryStream memStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memStream);

writer.Write((UInt16)10);   // Paklänger
writer.Write((Byte)0x11);   //videoID Byte 1 als hex
writer.Write((Byte)0x11);   //videoID Byte 2 als hex
writer.Write((UInt32)1000); //Hole Zählerwert mit 4 Byte
writer.Write((Int32)11);    //4 Byte reserve

byte[] DataPaket = memStream.ToArray();

beste Grüße
zommi

//Edit:
Und anstatt Array.Reverse(...) kannst du deinen Zahlwert auch mittels IPAddress.HostToNetworkOrder(...) nach BigEndian konvertieren.

08.12.2010 - 12:48 Uhr

Hi martin,

ich hoffe, ich habe dein Problem richtig verstanden:

Du möchtest eine Klasse xml-serialisieren, die intern Ableitungen eines Typs mitserialisieren soll. Allerdings bekommst du bei der jetzigen Variante einen Fehler.

Hierfür müssen dem XmlSerializer die zusätzlichen Typen bekannt gemacht werden.
*Entweder deklarativ und statisch per [XmlInclude(typeof(Message)), XmlInclude(typeof(Info)), XmlInclude(typeof(Error))] *Oder du verwendest die Überladung des Konstruktors XmlSerializer(Type type, Type[] extraTypes) um die anderen Typen mitzugeben.
(Das ist vor allem bei Plugin-Systemen relevant, wo du die Typen zur Compilezeit noch gar nicht kennen kannst)

beste Grüße
zommi

02.12.2010 - 15:24 Uhr

Schaut aber gut aus! 👍

Carl dankt dir ! 😉

Wegen Performance:
*Konvertiere die 4-Byte langen Byte[]-Arrays in einen Int32 (mit dem BitConverter) Verwende zwei Dictionaries, oder zwei HashSets anstatt den einfachen Arrays. So kannst du auf Kollisionen dank der schnellen Contains-Methode in insgesamt O(n+m) suchen anstatt wie bei dir (wegen der verschachtelten Schleife) in O(nm) *...

Diese beiden Punkte sollten schon reichen um nen ausreichenden Speedup zu gewährleisten.

Mein Referenzprogramm sah so aus:

static void Main(string[] args)
{
    string originTextForAlice = "Hiermit beschliessen Alice und Bob die Aufteilung der Beute. Alice bekommt 80 Prozent und Bob den Rest.";
    string originTextForBob = "Hiermit beschliessen Alice und Bob die Aufteilung der Beute. Bob bekommt 80 Prozent und Alice den Rest.";

    string finalTextForAlice = "", finalTextForBob = "";

    HashSet<uint> hashesAlice = new HashSet<uint>();
    HashSet<uint> hashesBob = new HashSet<uint>();

    IEnumerator<string> textsAlice = AllModifiedTexts(originTextForAlice).GetEnumerator();
    IEnumerator<string> textsBob = AllModifiedTexts(originTextForBob).GetEnumerator();

    while (textsAlice.MoveNext() && textsBob.MoveNext())
    {
        string textForAlice = textsAlice.Current;
        string textForBob = textsBob.Current;

        uint hashAlice = SpecialHash(textForAlice);
        uint hashBob = SpecialHash(textForBob);

        if (hashesAlice.Contains(hashBob))
        {
            finalTextForBob = textForBob;
            finalTextForAlice = AllModifiedTexts(originTextForAlice).First(s => SpecialHash(s) == hashBob);
            break;
        }

        if (hashesBob.Contains(hashAlice))
        {
            finalTextForAlice = textForAlice;
            finalTextForBob = AllModifiedTexts(originTextForBob).First(s => SpecialHash(s) == hashAlice);
            break;
        }

        hashesAlice.Add(hashAlice);
        hashesBob.Add(hashBob);
    }

    Console.WriteLine("{0}: {1}", SpecialHash(finalTextForAlice), finalTextForAlice);
    Console.WriteLine("{0}: {1}", SpecialHash(finalTextForBob), finalTextForBob);
}

static MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();

//---------------------------------------------------------------------
static uint SpecialHash(string s)
{
    return BitConverter.ToUInt32(MD5(MD5(ASCIIEncoding.ASCII.GetBytes(s))), 0);
}

//---------------------------------------------------------------------
static byte[] MD5(byte[] message)
{
    return md5Hasher.ComputeHash(message);
}

//---------------------------------------------------------------------
static IEnumerable<string> AllModifiedTexts(string s)
{
    return JoinWithOneOrTwoSpaces(s.Split(' '));
}

//---------------------------------------------------------------------
static IEnumerable<string> JoinWithOneOrTwoSpaces(IEnumerable<string> words)
{
    if (words.Count() == 1)
        yield return words.Single();
    else
        foreach (string suffix in JoinWithOneOrTwoSpaces(words.Skip(1)))
        {
            yield return words.First() + " " + suffix;
            yield return words.First() + "  " + suffix;
        }
} 

Aber wie dem auch sei, deine Lösung tuts, damit du bist nun dran ! 🙂

02.12.2010 - 10:52 Uhr

Hi nochma,

als typischer Stakeholder hab ich natürlich vergessen, die nichtfunktionalen Anforderungen zu spezifizieren 😉

Das Programm soll solch eine Kollision innerhalb weniger Sekunden finden! (vielleicht eine, oder auch zwei)

beste Grüße
zommi

02.12.2010 - 09:32 Uhr

Hi Pruit,

erstelle nur eine einzige Random-Instanz, dann funktioniert es auch. Beispielsweise als (statischen) Klassenmember.

Alt bekanntes Problem wie bei
Zufallsgenerator schnell hintereinander aufrufen
Zufallszahl in Schleife
Problem mit Würfelspiel (Randomfunktion)
...

Du erzeugst momentan ja in einer Schleife ständig neue Random-Instanzen, die defaultmäßig die aktuelle Zeit mit als Seed nehmen. In den aufeinanderfolgenden Schleifendurchläufen ist die Uhrzeit aber noch gleich, sodass auch die Random-Generatoren die selbe erste Zufallszahlen ausspucken. Wenn du hingegen im Debugger einzeln durchsteppst, dann erhöht sich damit die Zeit zwischen den Schleifendurchläufen drastisch, wodurch die Random-Instanzen mit unterschiedlichen Zeiten initialisiert werden.

beste Grüße
zommi

02.12.2010 - 00:22 Uhr

So,

dann mal ne kleine Geschichte:


Die drei globalisierten Bankräuber Alice, Bob und Carl sind seit ihrem letzten Streifzug ziemlich zerstritten. Da alle drei in unterschiedlichen Ländern wohnen, läuft ihre Kommunikations komplett über das Internet.

Als es um die Planung der Beute-Aufteilung zwischen Alice und Bob für den nächsten Deal geht, traut keiner dem anderen. Da macht Carl den Vorschlag, dass sie doch beide einen verbindlichen Vertrag eingehen, der die Aufteilung regelt. [Damit man seinen Teil der gestohlenen Beute auch gerichtlich einklagen kann 😉]

Carl bietet sich als Vermittler an, fertigt die Verträge aus und schickt sie Alice und Bob. Doch Carl will Alice und Bob noch ein wenig ärgern, und so möchte er den beiden jeweils unterschiedliche Verträge zusenden:

Hiermit beschliessen Alice und Bob die Aufteilung der Beute. Alice bekommt 80 Prozent und Bob den Rest.

Doch Alice und Bob vertrauen prinzipiell auch Carl nicht und vermuten bereits, dass er ihnen einen Streich spielen will. Deshalb einigen sie sich darauf, dass sie zuvor ihre Vertragstexte abgleichen. Da sie mal etwas von Digitalen Signaturen gehört haben, wollen sie diese nutzen und so meinen sie, dass es genügen sollte, die Hash-Werte der Vertragstexte zu vergleichen.

Da sie nur 4 Bytes für ihre Hashfunktion verschwenden möchten, überlegen sie sich ein cleveres Verfahren: Alice schlug vor, zunächst das MD5-Verfahren zu nutzen und einfach die ersten 4 Bytes zu nehmen. Bob wendet ein, dass damit ja die restlichen 12 Bytes des MD5-Wertes völlig unberücktsichtigt bleiben. Da kommt Alice wiederum die Idee einfach auf den MD5-Hash nochmal MD5 anzuwenden, um alle Bytes zu verwenden und von diesem neuen Hash die ersten 4 Bytes zu nehmen. Bob findet diesen Einfall brillant und so einigen sie sich auf:

SpecialHash(message) = First4Bytes(MD5(MD5(message))

(Message ist ASCII-kodiert)

Carl hat das mitbekommen, und so muss er zwei neue Vertragstexte anfertigen, die immernoch den beiden obigen ähneln, aber den selben Hash-Wert besitzen:

SpecialHash(SpecialTextForAlice) = SpecialHash(SpecialTextForBob)

Dabei bedeutet "ähneln", dass in den obigen Texten an beliebig vielen Stellen die [B]Leerzeichen [/B]durch [B]doppelte Leerzeichen[/B] ersetzt werden dürfen.

Damit wären also folgende Sätze ähnlich:

```
Das ist ein Satz.
Das ist ein Satz.
Das ist ein Satz.
Das ist ein Satz.


Hilf Carl mit einem C#-Programm dabei, zwei zu den obigen Vertragstexten ähnliche zu finden, die den selben Hash-Wert besitzen!

Viel Spaß beim Lesen und Implementieren ! 😃

beste Grüße
zommi

01.12.2010 - 16:11 Uhr

Hey,

ich ergänze folgenden Code: (nutzt .NET 4.0 Featur für named parameters)

    return (new BrutalCastContainer{BRef=null, ObjectRef=a}).BRef;
}
        
[StructLayout(LayoutKind.Explicit)]
struct BrutalCastContainer
{
    [FieldOffset(0)]
    public object ObjectRef;
    [FieldOffset(0)]
    public ClassB BRef;
}

Insgesamt also:

using System;
using System.Runtime.InteropServices;

class Aufgabe
    {

        class ClassA
        {
            public int fieldA;
            public void Test()
            {
                Console.WriteLine("method:A, Class:" + this.GetType().Name + ", fieldA:" + this.fieldA);
            }
        }

        class ClassB
        {
            public int fieldB = 0;
            public void Test()
            {
                Console.WriteLine("method:B, Class:" + this.GetType().Name + ", fieldB:" + this.fieldB);
            }
        }


        static void Main()
        {
            ClassA a = new ClassA();
            ClassB b = Magic(a);
            a.fieldA = 1337;
            a.Test();
            b.Test();
            Console.ReadLine();
        }

        // Start Magic-Code 
        private static ClassB Magic(ClassA a)
        {
		    return (new BrutalCastContainer{BRef=null, ObjectRef=a}).BRef;
		}
        
        [StructLayout(LayoutKind.Explicit)]
        struct BrutalCastContainer
        {
            [FieldOffset(0)]
            public object ObjectRef;
            [FieldOffset(0)]
            public ClassB BRef;
        }
        // End Magic-Code 
    }

beste Grüße
zommi

Ich grübel schonmal über ne neue Aufgabe...

01.12.2010 - 12:59 Uhr

Ich hätte niemals gedacht, das ich zommi in so einem Feld jemals korrigieren darf 😄

Ich habs ja auch extra zurückhaltend formuliert:

Jacks Effekt sollte nicht auftreten

😉

Worauf ich aber hinaus will: unsere Beiträge widersprechen sich ja nicht. 1.Beim Entnehmen von Fließkommazahlen aus der FPU wird stets Prozessor-seitig gerundet, da die FPU ja wie du sagst mit 80, 96 oder gar mit 120 Bit arbeiten. Ein Double aber in der "normalen Darstellung im Speicher" nur 64 Bit belegt. Dieses Runden passiert aber bei allen 3 Sprach-Snippets gleich. Die Schleifen-Variable bleibt anscheinend die ganze Zeit in der FPU, und zur Darstellung (und Umwandlung in ein int64) wird einmal CPU-seitig gerundet. Aber da alle Sprachen ja auf der selben Maschine laufen, runden sie alle identisch.

1.Zur Darstellung von Fließkommazahlen für das Dezimal-System muss Framework/Runtime (Java, .NET, CRT) da irgendwas umrechnen und gegebenfalls runden und abschneiden. Und das passiert in den drei Frameworks wohl unterschiedlich.

Insofern: Ja, Jacks Effekt tritt natürlich bei allen Snippets auf, da wir nen "FPU-Register => CPU-Register"-Transfer haben, aber für das von Scavanger eingangs beschriebene Phänomen ist nur die "Output-Methode" des jeweiligen Frameworks verantwortlich.

(Denn meine 3 Ausgaben zeigen ja, dass die Bytes der cpu-seitig gerundeten Werte noch identisch sind bei allen 3 Varianten)

beste Grüße
zommi

01.12.2010 - 11:21 Uhr

Hi,

ich habe mich mal dem Eingangsproblem gewidmet. Und bei genau diesem Code (double-Zähl-Schleife) rechnen alle Sprachen gleich. Jacks Effekt sollte nicht auftreten, da ja nirgends direkt gerundet wird (double nach int oder so).

Und siehe da, intern sind alle double-Werte identisch! Nur die Consolen-Ausgabe zeigt die Werte anders an. Um das nachzuweisen, hab ich zu die interne Byte-Repräsentation der double-Werte als 64-bit-Int interpretiert und ebenfalls ausgeben lassen. (Und bei der Ausgabe von Integer-Typen wird nicht gerundet)

Hier die drei Snippets:

class Test {
  public static void Main() {
    double i;
    long raw;
    for (i = 0; i <= 10; i += 0.1) {
      raw = System.BitConverter.ToInt64(System.BitConverter.GetBytes(i), 0);
      System.Console.WriteLine("{0}, {1}", raw, i);
    }
  }
}
#include <stdio.h>
void main() {
  double i;
  long long raw;
  for (i = 0; i <= 10; i += 0.1) {
    raw = *(long long*)&i;
    printf("%lld, ", raw);
    printf("%f\n", i);
  }
}
class Test { 
  public static void main(String[] args) {  
    double i;
    long raw;
    for (i = 0; i <= 10; i += 0.1) {
      raw = Double.doubleToRawLongBits(i);
      System.out.println(raw + ", " + i);
    }
  }
}

Und die ersten Zeilen der Ausgaben sind:

0, 0
4591870180066957722, 0,1
4596373779694328218, 0,2
4599075939470750516, 0,3
4600877379321698714, 0,4
4602678819172646912, 0,5
4603579539098121011, 0,6
4604480259023595110, 0,7
4605380978949069209, 0,8
4606281698874543308, 0,9
4607182418800017407, 1
4607632778762754457, 1,1
4608083138725491507, 1,2
4608533498688228557, 1,3
4608983858650965607, 1,4
4609434218613702657, 1,5
4609884578576439707, 1,6
4610334938539176757, 1,7
4610785298501913807, 1,8
4611235658464650857, 1,9
4611686018427387905, 2
...
0, 0.000000
4591870180066957722, 0.100000
4596373779694328218, 0.200000
4599075939470750516, 0.300000
4600877379321698714, 0.400000
4602678819172646912, 0.500000
4603579539098121011, 0.600000
4604480259023595110, 0.700000
4605380978949069209, 0.800000
4606281698874543308, 0.900000
4607182418800017407, 1.000000
4607632778762754457, 1.100000
4608083138725491507, 1.200000
4608533498688228557, 1.300000
4608983858650965607, 1.400000
4609434218613702657, 1.500000
4609884578576439707, 1.600000
4610334938539176757, 1.700000
4610785298501913807, 1.800000
4611235658464650857, 1.900000
4611686018427387905, 2.000000
...

0, 0.0
4591870180066957722, 0.1
4596373779694328218, 0.2
4599075939470750516, 0.30000000000000004
4600877379321698714, 0.4
4602678819172646912, 0.5
4603579539098121011, 0.6
4604480259023595110, 0.7
4605380978949069209, 0.7999999999999999
4606281698874543308, 0.8999999999999999
4607182418800017407, 0.9999999999999999
4607632778762754457, 1.0999999999999999
4608083138725491507, 1.2
4608533498688228557, 1.3
4608983858650965607, 1.4000000000000001
4609434218613702657, 1.5000000000000002
4609884578576439707, 1.6000000000000003
4610334938539176757, 1.7000000000000004
4610785298501913807, 1.8000000000000005
4611235658464650857, 1.9000000000000006
4611686018427387905, 2.0000000000000004
...

Also nochmal kurz: Intern rechnen alle 3 Sprachen gleich (und richtig), nur die Anzeige von Fließkomma-Zahlen ist unterschiedlich.

beste Grüße
zommi

23.11.2010 - 08:33 Uhr

Hi Hotzenplotz,


HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0

allerdings gibt es bei mir auch noch etwas wie

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config

beste Grüße
zommi

23.11.2010 - 08:30 Uhr

Hi,

when your application initializes, register a callback method with the AppDomain’s ResolveAssembly event

Darum würde ich es mal so probieren (nicht im Window, sondern in der Application):

Ich würde es nicht im Konstruktor ("public App(){...}") definieren, sondern im Typinitialisierer ("static App(){...}").

beste Grüße
zommi

19.11.2010 - 13:57 Uhr

Um Starlight's Antwort noch zu konkretisieren:
Mach aus deinem "&" ein "|".

beste Grüße
zommi

PS: Es heißt verbreiteter "GCD" und nicht "BCD"... greatest anstatt biggest.

05.11.2010 - 20:22 Uhr

Kommunikation? Über Netzwerk?
Warum dann nicht die Network-Byte-Order festlegen. Hält den Code auch portabel.

Für htonl usw. gibts in .Net bereits HostToNetworkOrder(...) bzw. NetworkToHostOrder(...).

beste Grüße
zommi

04.11.2010 - 18:50 Uhr

Byte-weise einlesen, Byte-weise abspeichern!

01.11.2010 - 16:59 Uhr

Hi jojo2100,
1.du wolltest wahrscheinlich mit deinem

(?=[^\.])

einen Lookbehind erzeugen, aber die Syntax ist dafür falsch. (deins ist ein lookahead) Es müsste zunächst wie folgt lauten:

(?<=[^\.])

Nun matcht das aber nicht auf die Variante, mit "nichts" davor, da du verlangst, dass ein Zeichen - und zwar ein Nicht-Punkt-Zeichen - davor kommt. Das ist zu restriktiv.

Was du eigentlich willst, ist dass kein Punkt davor ist! Kleiner aber feiner Unterschied:

"Kein Punkt davor" != "Ein Nicht-Punkt-Zeichen davor"

Insofern bieten sich also negierte Lookbehinds an:

(?<!\.)

1.Ein ähnlicher Denkfehler ist beim Lookahead. Wenn du an deinen Beispiel-Text noch eine Zeile "(Cmd" anhängst, detektiert er dort das Cmd nicht. Denn auch hier gilt:

"Ein WhiteSpace dahinter" != "Kein Nicht-Whitespace dahinter (höchstens ein WhiteSpace dahinter)"

Deshalb solltest du es negieren:

(?!=[^\s])

und dann für die Klasse [^\s] auch das Surrogat \S verwenden:

(?!=\S)

Nun kommt aber erschwerend noch hinzu, dass standardmäßig ein "leerer String" auch die Bedingung "kein Nicht-White-Space" erfüllt. Also ist dieses Lookahead bisher sinnlos, weil es immer und überall matcht. Damit er nicht einfach nen leeren String matcht, müssen wir das gierige Verhalten umstellen und ein "?"-Switch einbauen.

Insgesamt ergibt sich dann wohl:

(?<!\.)Cmd(?!=?\S)

beste Grüße
zommi

PS: Ich weiß, doppelte Negation ist immer tricky ;D

30.10.2010 - 16:22 Uhr

Ein episch guter Film:

Scott Pilgrim Vs. The World

Der wie ich finde beste Film des Jahres! Geile Story, witzig, rasant, actionreich, phänomenal filmisch umgesetzt!

29.10.2010 - 15:49 Uhr

Hi,

kann ich gleichzeitig in einem weiteren thread diese Methode aufrufen und bearbeiten?

Wenn diese "thread-safe" ist, dann ja. Meistens ist das aber nicht der Fall.

Generell schreit dein Szenario aber mehr nach Asynchronität und weniger nach direktem Threading. Verwende doch zunächst die BeginXXX und EndXXX Methoden, bevor du direkt mit eigenem Threading anfängst.

beste Grüße
zommi

20.10.2010 - 19:51 Uhr

Hi,

**baseAddress **und offset sind auch nur Platzhalter, die du durch deine echten Variablennamen ersetzen musst ;D

Aber das Prinzip wollt ich damit aufzeigen.

beste Grüße
zommi

20.10.2010 - 19:44 Uhr

Hi Sebastian,

vielleicht hilft ja schon LINQ selbst weiter 😃

static IEnumerable<DateTime> EnumerateDateTimes(int startYear, int endYear, IList<DayOfWeek> possibleDays, int startHour, int endHour)
        {
            return Enumerable.Range(startYear, endYear-startYear+1)
                .SelectMany(year => EnumerateDaysInYear(year, possibleDays, startHour, endHour));
        }

        static IEnumerable<DateTime> EnumerateDaysInYear(int year, IList<DayOfWeek> possibleDays, int startHour, int endHour)
        {
            return Enumerable.Range(1, 12)
                .SelectMany(month => EnumerateDaysInMonth(year, month, possibleDays, startHour, endHour));
        }

        static IEnumerable<DateTime> EnumerateDaysInMonth(int year, int month, IList<DayOfWeek> possibleDays, int startHour, int endHour)
        {
            return Enumerable.Range(1, DateTime.DaysInMonth(year, month))
                .Select(day =>new DateTime(year, month, day))
                .Where(date => possibleDays.Contains(date.DayOfWeek))
                .SelectMany(date => EnumerateHoursInDay(date, startHour, endHour));
        }

        static IEnumerable<DateTime> EnumerateHoursInDay(DateTime date, int startHour, int endHour)
        {
            return Enumerable.Range(startHour, endHour - startHour + 1)
                .Select(hour => date + new TimeSpan(hour, 0, 0));
        }

        static void Main(string[] args)
        {
            var days = EnumerateDateTimes(
                2004,
                2006,
                new[] { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday },
                8,
                16).ToList();


            foreach (DateTime day in days)
            {
                Console.WriteLine(day);
            }

        }

beste Grüße
zommi

20.10.2010 - 19:04 Uhr

Hi CrimeTime,

natürlich gehört das irgendwo zu den Grundlagen. Insbesondere das selbständige Herausfinden, woher die Exception wirklich herkommt. Wie im angehängten Screenshot beschrieben, siehst du, wie du über die Exception-Details rausfinden kannst, dass die Exception ihren Ursprung bei

System.IntPtr.op_Explicit(Int64 value)

nimmt. Warum wird diese Methode aufgerufen? Weil es keinen explicit Cast von uint (Uint32) nach IntPtr gibt. Deshalb erweitert er dein uint ohne Wertverlust auf long (Int64) und nutzt diesen Cast-Operator.

Auf der msdn-Seite zu Int64->IntPtr steht nun aber auch

OverflowException
On a 32-bit platform, value is too large to represent as an IntPtr.

Und da dein uint-Wert größer als der int-Wertebereich ist, gibts auf deinem 32-Bit-System ne Exception. (Wenn du selbigen Code auf der 64-Bit Maschine ausführst, gibts keine Exception)

uint und IntPtr harmonieren eben nicht.
Dafür gibt es int & IntPtr bzw. uint & UIntPtr. (Oder auf nem 64Bit System jeweils long und ulong)

Aber solche Pointer-Arithmetik sind ziemlich hässlich. Liest du aus dem Hauptspeicher? Aus einer Datei?

Und warum nutzt du überhaupt uint? Wenn es Zeiger sind, dann solltest du sie auch als IntPtr speichern. (Womit das Casten überflüssig wird).
Falls du dann noch noch PointerArithmetik brauchst und einen Offset draufaddieren musst, kannst du entweder die ab .NET 4.0 verfügbare Methode IntPtr.Add(...) bzw. die passende Operatorüberladung nutzen, oder aber du nutzt das nachfolgende Idiom:

IntPtr baseAddress; 
IntPtr targetAddress = new IntPtr(baseAddress.ToInt64() + offset);

Durch die Int64-Konvertierung läuft das sowohl auf nem 64-Bit, als auch auf nem 32-Bit System.

beste Grüße
zommi

20.10.2010 - 14:00 Uhr

Visual Paradigm for UML (gibts auch als Community Edition)

beste Grüße
zommi

19.10.2010 - 13:40 Uhr

Hi,

Beachte dabei, das einmal geladene Assemblys nicht wieder entladen werden können, ohne dabei die gesamte Appdomain zu entladen.

Ab .NET 4.0 geht das schon:

Zitat von: Zommis Blog: "DynamicMethod vs. DynamicAssembly"
[...] seit .NET 4.0 gibt es das Konzept der
>
. Beim Erzeugen einer neuen dynamischen Assembly übergibt man einen gewünschten
>
-Wert, der für .NET 4.0 um den
>
erweitert wurde. Ist dies aktiviert, sorgt die Laufzeitumgebung dafür, dass eine nicht mehr benötigte Assembly automatisch wieder entladen wird! Microsoft musste dafür zwar kräftig an dern CLR-Innereien werkeln, aber im Rahmen der DLR ist das Entladen von dynamisch erzeugten Typen für dynamische (Skript-)Sprachen unumgänglich. [...]

beste Grüße
zommi

16.10.2010 - 11:30 Uhr

Hi,

google@"sharp develop portable"
liefert mir beispielsweise direkt
devbar.de: SharpDevelop Portable 3.2

Noch als minimalistischere Alternative wäre der Snippet Compiler zu nennen. Intellisense is mit dabei. Nur echtes Projekt-Management nicht - eben nur für Snippets.

beste Grüße
zommi

15.10.2010 - 14:02 Uhr

Hi,

deine Aufgabenstellung ist das SubSetSum-Problem. (und damit ähnlich zum Rucksackproblem)

@Anzahl der Kombinationen
Bei n Einzelbeträgen gibt es 2^n Möglichkeiten eine Teilmenge und damit eine "Rechnung" zusammenzustellen. (jedes element nehmen oder nicht nehmen)

@ProblemLösung
Da es 2^n Möglichkeiten durchzuprobieren gilt, liegt das Problem in NP. Es ist sogar NP-vollständig. Allerdings gibt es einen (pseudopolynomiellen) Algorithmus, der das Problem mittels dynamischer Programmierung löst.

Wenn du danach googlest, solltest du was finden. Aber mit Sicherheit helfen dir auch die folgenden Posts, bei denen sogar schon Code und weitere Erläuterungen bei sind.
Alg. gesucht: Gegebene Zahl (=Summe) aus Menge von zufälligen Summanden bilden
Rucksackproblem ähnlich

beste Grüße
zommi

15.10.2010 - 13:55 Uhr

Hi,

Ich habe das über einen Threadpool mal getestet und zumindest auf den Arbeitsrechnern war das nicht gerade schnell.

Hast du trotzdem die blockierende API-Verwendet ? (ohne Async, etc) Dann kann das nicht viel schneller sein. Denn selbst wenn du den ThreadPool verwendest, blockieren ja deine Worker. Und .NET erstellt nur naaaach und nach ( so im 2sekunden-Takt) neue Threads, wenn die alten blockiert sind.

IO-Sachen, wie Netzwerk zu parallelisieren geht **immer **über die asynchrone IO-Variante.

Vielleicht hilft dir auch:
Viele Pings mit nicht sichergestelltem existierendem Hostnamen
Abarbeitung einer Liste auf mehrere Threads aufteilen
beste Grüße
zommi

15.10.2010 - 12:04 Uhr

Hi

Ich gehe bisher davon aus, dass ich das fs.Close() nicht aufrufen muss, da dies durch das Dispose() erledigt wird. Sehe ich das Richtig?

Jup, das Dispose reicht.

Was ich jedoch nicht versteht ist, warum der mit jeder geschriebenen Datei ansteigt.

Der Kernel hat nen sogenannten CacheManager, der Dateien cachet, falls man nochmal drauf zugreift, etc. Und Solange der Speicher nicht knapp wird, wird er den auch nicht freigeben - warum auch?!

Das wär zumindest meine Vermutung. Du kannst ja mal mit dem perfmon dir den Verlauf von "System::CacheBytes" anschauen (so heißt es bei mir).

beste Grüße
zommi

14.10.2010 - 10:24 Uhr

Aber welche Zielklasse (anstelle FileStram) verwende ich, wenn ich kein File will?

Der Vollständigkeit halber noch der Link auf die MSDN-Seite, die solche Informationen bietet: System.IO.Stream: Vererbungshierarchie.

beste Grüße
zommi

13.10.2010 - 22:01 Uhr

Hi,

Mir war gerade so "langweilig" dass ich folgendes fabriziert hab.

Mir auch ! 😁

Man kann die objektorientierte (Referenzen nutzendene) Implementierung von natürlichen Zahlen relativ kanonisch aufsetzen: Es gibt die Null als Zahl und es gibt den Nachfolger einer Zahl. Der Rest ergibt sich 😉 (So ist beispielsweise die "5" der 5-fache nachfolger der Null. )

Addition und (saturierte) Subtraktion hab ich auch implementiert. Der Großteil der Logik (aka "Magie") steckt in dem objektorientierten Methoden-Dispatch-Mechanismus, der abhängig vom Typ die richtige Methode aufruft. Für die elegante Implementierung dann noch etwas Double-Dispatching, viel Rekursion und tadaaaa:

public abstract class Number
{
    public static Number operator+(Number x, Number y) { return x.Add(y); }
    public static Number operator-(Number x, Number y) { return y.ReverseSub(x); }

    abstract internal Number Add(Number other); // zwei Zahlen addieren
    abstract internal Number ReverseSub(Number other); // zwei Zahlen umgekehrt subtrahiere, damit das Dispatching klappt
    abstract internal Number SubSuccessor(Successor other); // einen Nachfolger subtrahieren

    public static Number Zero { get { return new ZeroNumber(); } }

    #region Nur zur Kommunikation mit der struct-verwöhnten Außenwelt
    abstract public uint Value { get; }

    public static Number FromValue(uint value)
    {
        return (value == 0) ? Zero : new Successor(FromValue(value - 1));
    }
    #endregion

    internal class ZeroNumber : Number
    {
        internal ZeroNumber() { }
        override internal Number Add(Number other) { return other; } // 0+x=x
        override internal Number ReverseSub(Number other) { return other; } // x-0=x
        override internal Number SubSuccessor(Successor other) { return this; } // 0-x=0 (saturiert)

        public override uint Value { get { return 0; } }
    }

    internal class Successor : Number
    {
        private Number predecessor;

        internal Successor(Number predecessor) { this.predecessor = predecessor; }
        override internal Number Add(Number other) { return this.predecessor.Add(new Successor(other)); } // x+y = (x-1)+(y+1)
        override internal Number ReverseSub(Number other) { return other.SubSuccessor(this); } // DoubleDispatch
        override internal Number SubSuccessor(Successor other) { return other.predecessor.ReverseSub(predecessor); } // x-y = (x-1)-(y-1)

        public override uint Value { get { return predecessor.Value + 1; } }
    }
}

Und verwendet wirds dann halt so:

class Program
{
    static void Main(string[] args)
    {
        Number a = Number.FromValue(9);
        Number b = Number.FromValue(13);
        Number sum = a + b;
        System.Console.WriteLine("{0}+{1}={2}", a.Value, b.Value, sum.Value); // 9 + 13 = 22
        System.Console.WriteLine("{0}-{1}={2}", sum.Value, b.Value, (sum - b).Value); // 22 - 13 = 9
        System.Console.WriteLine("{0}-{1}={2}", sum.Value, a.Value, (sum - a).Value); // 22 - 9 = 13
    }
}

Also mir gefällt das 🙂
Bringt uns zwar nicht weiter, aber man kann schon ganz schön weit gehen mit der struct-losen Welt. (So sind in Smalltalk beispielsweise True und False auch zwei Singleton-Objekte und keine "Werttypen")
beste Grüße
zommi