Laden...

Forenbeiträge von OlafSt Ingesamt 79 Beiträge

20.08.2015 - 15:33 Uhr

bei stackoverlow gibts da eine schöne Erklärung:

Ursprünglich waren "&&" und "||" rein logische Operatoren, während "&" und "|" rein binäre Operatoren waren. Irgendwann hat man die Sprachen dahingehend erweitert, das die Benutzung von "&" und "|" in rein logischem Kontext zur vollständigen Auswertung des Ausdrucks führt, wärend "&&" und "||" auf "Kurzschluß-Verfahren" umgemünzt wurden.

So ist es nun absolut möglich, solche Konstrukte zu bauen:


a=null;
if ((a != null) && (a > 4)) { ... }

Ist einer der Vergleiche in einem AND-Ausdruck false, ist das gesamte Ergebnis false. Da "a != null" bereits false ist, wird "a > 4" gar nicht erst geprüft - das Ergbniss kann eh nicht mehr true werden 😉 Dies ist die "short curcuit evaluation".

Benutzt man dagegen

a=null;
if ((a != null) & (a > 4)) { ... }

und a ist tatsächlich null, dann knallts, denn der Ausdruck "a > 4" wird, obwohl das Ergebnis bereits feststeht, dennoch ausgewertet.

Das gleiche funktioniert mit dem "||" bzw. "|" ganz genau so.

Benutzt man "&" und "|" dagegen nicht in einem Logik-Kontext, dann wird das ganze als binärer Operator betrachtet. so kann man z.B. sehr einfach das Bit 4 in einem Integer setzen: i = i | (1 << 3) oder kürzer i = i | 8 oder noch kürzer i |= 8.

06.08.2015 - 14:57 Uhr

Du wartest doch gar nicht:

  
var Res=ScanFilesRecursiveAsync(DirInfo.FullName, Extensions);  
  

=>

  
return await Task<List<string>>.Run(async () =>  
...  
var Res=await ScanFilesRecursiveAsync(DirInfo.FullName, Extensions);  
  

8o ⚠

Ich habe mich immer gefragt, warum ich nicht "var Res=await Scan... " aufrufen konnte - der Compiler hat sofort losgemosert. Jetzt ist mir das klar: Der Delegat muß auch einen async-Modifizierer haben. Einmal async, immer und überall async.

Mit dieser Änderung entstehen nun erheblich weniger Threads (17, ab und zu ein 18.) - wie ich es eigentlich schon am Anfang erwartet hatte. Dem Gerappel auf der Platte nach zu urteilen warten die nun auch fleißig aufeinander. Nichts anderes wollte ich erreichen: Es sollte immer nur ein Task zur Zeit aktiv mit dem Laufwerk arbeiten, alle anderen sollten abwarten (bin schon vor 2 Dekaden, als Multithreading aufkam, über dieses problem gestolpert). Zugleich will ich aber meine GUI aktiv behalten.

Cleverer waäre es natürlich gewesen, das gleich in einen einzelnen Task oder Thread zu stecken, aber dann hätte ich halt nicht kapiert, wie async/await funktioniert und wie es korrekt benutzt wird.

Ist euch sonst noch eine Häßlichkeit aufgefallen, die man als fähiger C#-Programmierer nicht machen sollte ?

06.08.2015 - 11:07 Uhr

Darum auch meine Frage: Laufen diese Tasks wirklich alle nebeneinander her ? Wenn ja, welchen Sinn hat dann "await" ? So wie ich das verstanden habe, wartet "await" quasi doch darauf, das der Task durchgelaufen ist...

Ansonsten ist es mir schon klar, das man den Schreib-Lese-Kopf nicht überfordern sollte 😉

06.08.2015 - 10:12 Uhr

Hallo Freunde,

ich habe mich mal an ein für mich nützliches Utility gemacht. Im wesentlichen ist das nur ein Dateiscanner, der aber die gefundenen Dateien später im gesamten Haus-LAN verfügbar machen soll.

Kernstück des ganzen ist natürlich die Dateisuche und mich nervte die Tatsache, das die GUI dabei einfriert. Schreit ja nach async/await 😁

Zum testen also einfach ein WinForm aufgemacht, ein Menü drauf, eine Listbox und zwei Labels.

Der Handler für den Menüpunkt wirft die ganze Arie an und erwartet eine Liste mit Dateinamen zurück. Diese Liste wird in die Listbox gefüllt und noch ein bissel Prosa ausgegeben:


        private async void filmeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileScanClass fsc = new FileScanClass();
            fsc.OnScanDirectory += OnScanDirectory;


            List<string> li=await fsc.ScanFilesRecursiveAsync("C:\\", new string[] {"*.ts"});
            for(int i=0; i<li.Count;i++)
               listBox1.Items.Add(li[i]);
            label1.Text = "Durchsuchtes Verzeichnis: fertig";
            MessageBox.Show(string.Format("Scan complete. Directories scanned: {0}. Files found: {1}", fsc.DirsScannedCount, li.Count));
        }

Ich habe das ganze Filescanning in eine eigene Klasse verpackt, die aus Jux und Dollerei für jedes durchsuchte Verzeichnis einen Event auslöst. So kann die GUI dem Benutzer anzeigen, das was passiert - etwas, das seit Windows 8 völlig aus der Mode kommt.

Durch Async/Await scheint das ganze in einem eigenen Thread zu laufen, weshalb hier kräftig Invoked werden muß:


        private void OnScanDirectory(object sender, ScanDirectoryEventArgs e)
        {
            if (label1.InvokeRequired)
            {
                label1.Invoke(new MethodInvoker(delegate
                {
                    label1.Text = "Durchsuchtes Verzeichnis: " + e.DirectoryName;
                    label2.Text = "Durchsuchte Verzeichnisse: " + e.ScanCounter.ToString();
                    label1.Update();
                    label2.Update();
                }));
            }
            else
            {
                label1.Text = "Durchsuchtes Verzeichnis: " + e.DirectoryName;
                label2.Text = "Durchsuchte Verzeichnisse: " + e.ScanCounter.ToString();
                label1.Update();
                label2.Update();
            }
        }

Fehlt uns nur noch die eigentliche Dateisuche selbst, respektive die Klasse, die ich dazu gebastelt habe (///-Tags entfernt, der Post ist schon lang genug):


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MScanner
{
    public class ScanDirectoryEventArgs : EventArgs
    {
        private string DirName;
        private long ScanCount;

        public ScanDirectoryEventArgs(string Dir, long ScanCounter)
        { 
            DirName = Dir;
            ScanCount=ScanCounter;
        }
        public string DirectoryName
        {
            get
            {
                return DirName;
            }
        }
        public long ScanCounter
        { 
            get 
            { 
                return ScanCount; 
            } 
        }
    }

    class FileScanClass
    {
        public delegate void ScanDirectoryEventHandler(object source, ScanDirectoryEventArgs e);
        public event ScanDirectoryEventHandler OnScanDirectory;
        private long _DirCount;

        public long DirsScannedCount { get {return _DirCount;} }

        public FileScanClass()
        {
        }

        public async Task<List<string>> ScanFilesAsync(string SourceDir, string Extension)
        {
            return await ScanFilesAsync(SourceDir, new string[] { Extension });
        }

        public async Task<List<string>> ScanFilesAsync(string SourceDir, string[] Extensions)
        {
            return await Task<List<string>>.Run(() =>
                {
                    List<string> li = new List<string>();
                    DirectoryInfo di = new DirectoryInfo(SourceDir);
                    if (OnScanDirectory != null)
                        OnScanDirectory(this, new ScanDirectoryEventArgs(SourceDir, _DirCount));
                    _DirCount++;  //Kein wirkliches Multithreading, sollte also safe sein
                    foreach (string s in Extensions)
                    {
                        FileInfo[] fi = di.GetFiles(s);
                        foreach (FileInfo f in fi)
                        {
                            li.Add(f.FullName);
                        }
                    }
                    return li;
                });
        }

        public async Task<List<string>> ScanFilesRecursiveAsync(string SourceDir, string[] Extensions)
        {
            return await Task<List<string>>.Run(() =>
            {
                DirectoryInfo[] Dirs;

                List<string> li = new List<string>();
                DirectoryInfo di = new DirectoryInfo(SourceDir);
                if (OnScanDirectory != null)
                    OnScanDirectory(this, new ScanDirectoryEventArgs(SourceDir, _DirCount));
                Interlocked.Increment(ref _DirCount); //Durch Multithreading muß das abgesichert sein
                try
                {
                    Dirs = di.GetDirectories();
                }
                catch (UnauthorizedAccessException)
                {
                    //Kein Zugriff auf dieses Verzeichnis, also leere Liste
                    //und weg hier
                    return li;
                }
                foreach(DirectoryInfo DirInfo in Dirs)
                {
                    var Res=ScanFilesRecursiveAsync(DirInfo.FullName, Extensions);
                    li.AddRange(Res.Result);
                }
                foreach (string s in Extensions)
                {
                    FileInfo[] fi = di.GetFiles(s);
                    foreach (FileInfo f in fi)
                    {
                        li.Add(f.FullName);
                    }
                }
                return li;
            });
        }
    }
}

Es gibt dort zwei Methoden, die die Arbeit verrichten. ReadFilesAsync liest nur ein einzelnes Directotry aus; ReadFilesRecursiveAsync macht das auch, wandert aber auch durch eventuell vorhandene Unterverzeichnisse (underen Unterverzeichnisse etc) hindurch. Von Interesse ist auch nur die rekursive Methode, diese wird primär zum Einsatz kommen.

Meine Frage zu diesem Stück Code:

Es entstehen gewaltige Mengen an Threads, wenn diese Routine z.B. auf C:\ losgelassen wird (bis zu 40 zeigt der Taskmanager an). Da mir die Funktion von Async/Await noch immer ein wenig schleierhaft ist: Laufen diese wirklich alle zeitgleich oder wartet der Task, der gerade C:\Windows durchsucht, auf den Task, der C:\Windows\System32 durchsucht - der auf den Task wartet, der C:\Windows\System32\Microsoft durchsucht ?

Danke fürs drüberschauen.

23.07.2015 - 01:12 Uhr

EDIT: Eine Sache habe ich noch nicht verstanden. Wenn ich mit func die Signatur vorgebe - wie und warum funktioniert der Parameterlose Aufruf??

Ich bezweifle, das das ernsthaft parameterlos ist. Die Deklaration von converter.ConvertMyObjectToString ist mit sicherheit irgendwas in der Art

public string ConvertMyObjectToString(T, int VerySpecialNeededNumber)

Du meldest ja in der Parameterliste einen Func<T, int, string> an. Damit ist nur der Name der Methode gemeint, die letztlich ausgeführt werden soll. Die Parameter für diese auszuführende Methode kommen ja woanders her:

sb.AppendLine(method(item, counter));

item und counter sind die Parameter, die an ConvertToMyObject übergeben werden - ergo an den Func<T, int, string> (string ist der Rückgabewert, kein Parameter !). Die Params müssen natürlich nicht mitangegeben werden, nur der Methodenname ist von Belang - ob die angegebene Methode auch paßt, prüft der Compiler.

Ich hoffe, das war verständlich. Ich habe auch ne ganze Weile damit auf Kriegsfuß gestanden, bis ich mir vor Augen gehalten habe, wie das in Delphi/Object Pascal letztendlich aussehen würde. Da gibts sowas auch.

23.06.2015 - 23:21 Uhr

Der Autor vom UpdateSystem.NET ist sehr aktiv bei VB-Paradise - IIRC hat er das dort sogar als erstes vorgestellt. Vielleicht fragst da nochmal nach 😉

18.06.2015 - 13:09 Uhr

Das der Pacman beim Abbiegen an einer Wand oder Ecke hängen bleibt, ist n bissel nervig 😉 Der geübte WASD-WoW-Zocker kriegt da schnell ne Zornesader :auf der Stirn 😁 Aber dagegen gibt es ein Mittel. Das original-Pacman aus den 70er Jahren ist einfach so lange in die bisherige Richtung weitergelaufen, bis es abbiegen konnte - allerdings nur solange, bis es einen (oder waren es zwei ?) "Freßpunkte" überquert hatte (unabhängig davon, ob der Punkt nun tatsächlich gefressen wurde oder nicht). Jedes Kommando zur Richtungsänderung hat diese "Warten bis ich abbiegen kann" natürlich überschrieben.

Ansonsten finde ich das ganze echt gelungen - den Code habe ich mir allerdings nicht angeschaut, der ist ausdrücklich aus dieser Wertung ausgenommen 😁

04.06.2015 - 13:12 Uhr

Das stimmt, sie benutzen den gregorianischen Kalender. Darum ist der 02.06.2015 in unseren Breiten auch der 02.06.2015 in China. Keine Frage. Aber die Chinesen haben eine eigentümliche Schrift und ich habe den 02.06.2015 in Chinesisch auch hier posten wollen - nur leider kriegt das Forum das nicht so ganz hin.

Darum hänge ich das genannte Datum in chinesischer Form mal hier als PNG dran. In der ersten Zeile, wie es üblicherweise geschrieben wird, darunter die verwestlichte Form mit Zahlen wie wir sie kennen.

02.06.2015 - 13:27 Uhr

Das ist sehr löblich - aber IMHO der falsche Weg.

benutzerdefinierte Formatierungen betreffen nicht nur Währungen (von denen du übrigens nicht alle Optionen anbietest - Währungskennzeichen und -position anyone ?). Das Spiel geht weiter mit Datumsangaben: Trenner zwischen den einzelnen Elementen, Position der einzelnen Elemente, 2- oder 4-stellige Jahreszahl und und und. Und das ganze nocheinmal für die Uhrzeit.

Tatsächlich ist es so, das der Benutzer in der Regel genau weiß, welche Landesspezifische Formatierung er gerne haben will. Wenn jemand die en-US-Formatierung für Währungen will, dann will er fast immer auch das Datum in en-US. Windows hat weit über 150 verschiedene, länderspezifische Formatierungen in seinen Innereien (und da gibt es echt einige haarsträubende Exoten drunter), die du erst umständlich nachprogrammieren müßtest. Spätestens bei den Chinesen, wo der 02.06.2015 überhaupt keine von uns gewohnte Formatierung besitzt (ja nicht mal entsprechende Symbole), bist du geplatzt 😉

Ich würde dem User eine Liste der verfügbaren Formatierungen anbieten und damit dann arbeiten.

12.05.2015 - 14:31 Uhr

Unter den elf Kollisionen sind allein sieben Auffahrunfälle - und dagegen, schreibt Google-Manager Urmson, könne derjenige, auf den der Hintermann auffährt, nur wenig tun. Das Problem hat ein computergesteuertes Auto natürlich genauso wie jeder menschliche Fahrer.

Verzeihung, aber da liegt der Google-Manager falsch. Natürlich gibt es eine Gegenmaßnahme gegen Auffahrunfälle. Nennt sich Sicherheitsabstand.

Nichtsdestotrotz ist die Leistung dieser autonomen Fahrzeuge echt beeindruckend.

10.05.2015 - 11:54 Uhr

Also ehrlich, Freunde - hier wird erst mit Granaten und dann mit taktischen Nuklearsprengköpfen auf Spatzen geschossen. Für dieses simple Problem den blutigen Anfänger mit Threads, Synchronisierung und Async zu konfrontieren macht aus dem Anfänger einen "das kapier ich nie, lassen wir das".

Das Problem läßt sich sehr einfach lösen:

Der Timer wird initial auf 10 Sekunden gestellt. Dann löst der Timer den ersten Button aus. Innerhalb des Button-Handlings wird der Timer ausgeschaltet, die Routine läuft, am Ende stellt sie den Timer auf 2 Sekunden und startet ihn wieder.

Dadurch löst der Timer den 2. Button ziemlich genau 2 Sekunden nach Ende von Button1Click() aus. Im Handler für den zweiten Button passiert dasselbe in Grün: Timer ausknipsen, Routine laufen lassen, Timer auf 10 Sekunden stellen und Timer anknipsen.

Keine Threads, kein Async-Geraffel, nix dergleichen 😉

27.02.2015 - 15:39 Uhr

Zunächst einmal liegt es mir fern, eine "Privataudienz" oder ähnliches einzufordern, geschweige denn zu erwarten. Erstaunlich, wie schnell man in ein falsches Licht geraten kann 😄 Mir gehts nicht ums Copyright oder Geld oder so ein Schmu. Einen Entwicklerkreis, in dem man sich Face-to-Face austauschen kann, hätte ich auch gern - ist aber in dieser Gegend und mit meinen Lebensbedingungen schlicht nicht machbar. Mir bleiben nur Foren für den Austausch von Gedanken und ich helfe in solchen auch gern bei Problemen in der Programmierung - mir wird da schließlich auch geholfen. Aber ich "schubse nur in die passende Richtung" (und erwarte auch nichts anderes). Laufen muß man schon selbst.

Nun habe ich da ein Stück Code - so um die 500 Zeilen. Ist eine Portierung aus Delphi nach C# und ich hätte dieses Stück Code gern mal begutachtet von Leuten, die C# schon etwas länger machen. Ist ja gut möglich (oder eher: fast sicher) das meine C#-Portierung noch viel zu "Delphisch" ist. Aber als Alleinkämpfer in der Wüste erkennt man das nie und nimmer. Da bietet sich die Review-Abteilung ja geradezu an.

Wäre das schon eine Nummer zu groß für den Code-Review ?

27.02.2015 - 13:34 Uhr

Es ist die Frage, ob "erwachsen" das richtige Wort ist 😉

Ohne Frage war dieses Forum ausgesprochen Neuling-Feindlich. Ich programmiere schon einige Dekaden lang in den verschiedensten Sprachen und war schon in Foren unterwegs, als die Dinger noch gar nicht so hießen 😉 Aber nirgendwo bin ich derart abgekanzelt worden wie hier.

Das ist verständlich, wenn das Forum auf der Fahne hat "nur für Fortgeschrittene". Nun - Anfänger sind potentielle Fortgeschrittene. Fatalerweise kommt von 1000 so harsch abgefertigten, potentiellen Fortgeschrittenen bestenfalls ein einziger irgendwann nochmal hierher. Das Forum hat keinen Zuwachs, und wenn irgendwann alteingesessene User abspringen (Jobwechsel, Berufswechsel zum Gärtner usw), dann stirbt so ein Forum.

Ich habe das auch so getan, denn trotz 30 Jahre Programmierung war ich Anfänger in C#. Ich wußte damals schon, wie Threads funktionieren, wie man sie ausbaut, synchronisiert und Deadlocks vermeidet - nur eben nicht in C#. Im wesentlichen wurde mir hier n kalter Lappen ins Gesicht geschmissen und gesagt: Komm in 5 Jahren wieder. Also hab ich mir meine Fragen woanders beantworten lassen (VB-Paradise ist da wirklich zuvorkommend) und hier nur sporadisch mal reingeschaut.

Warten wir ab, wie sich die Beginners Section entwickelt und besonders interessant finde ich die Review-Ecke. Hätte da einiges zur Überprüfung in petto - aber ich mag meinen Code auch nicht unbedingt ins Netz stellen, wo er dann von jedermann einfach kopiert werden kann. ich schau es mir aber definitiv an.

25.02.2015 - 10:15 Uhr

Dann wirds wohl nicht am Speicher liegen.

Ist vielleicht mal interessant, sie die SQL-Statements genauer anzusehen und mal einen Query-Plan machen zu lassen. Würde mich nicht wundern, wenn da der Hund begraben liegt...

23.02.2015 - 15:08 Uhr

Den OperationalStatus auszuwerten (und nicht nur anzuzeigen) hilft sehr dabei, solche offenkundig unsinnigen IP-Adressen gar nicht erst als "gültig" zu erkennen. Mit anderen Worten: Ist operationalStatus != OperationalStatus.Up, ist keine IP-Adresse vorhanden. Völlig egal, was der Treiber einem sonst vorgaukelt.

29.09.2014 - 10:06 Uhr

Logging ist doch nur während der Entwicklungsphase und in den ersten Laufzeit-Tagen bzw. -Wochen wirklich noch für die Fehlersuche.

Danach dient das Logging als Nachweis, das die eigene Software sauber funktioniert und somit "andere" Schuld sind, das es plötzlich nicht mehr funktioniert. Darum sind die Logfiles auch Anfangs kompakt, nur für den Entwickler verständlich 😉 und schnell geschrieben. Ist man dann in der "Beweisphase" angekommen, explodieren die Logfiles, weil man plötzlich wirklich alles mitloggen muß und das auch noch so verständlich, das die Troubleshooter, die nun mit der Software umgehen sollen, das auch kapieren.

04.10.2013 - 11:09 Uhr

Mein erstes Projekt... Oha, das ist lange her.

Damals baute mein Vater zusammen mit einem inzwischen verstorbenen Bekannten den Norddeutschen Billard-Verband auf. In unserem hiesigen Pool-Verein trugen wir schon kleinere interne Turniere aus, um die Rangliste innerhalb des Vereins zu ermitteln. Alles noch auf Papier, es war ein Alptraum.

Irgendwann kam mein Vater auf mich zu (ich damals 14 Jahre jung) und fragte mich, ob man das nicht auf dem Computer machen könnte. Und so bastelten wir unsere erste Turnier-Auswertung zusammen. Maximal 16 Spieler, einfaches K.O.-System.

Dieses Programm schlug ein wie eine Granate, nachdem wir es mit AV-Signalmultiplizierern hinbekommen hatten, die laufende Auswertung auch noch auf mehreren Fernsehern anzeigen zu können. So reichten die 16 Spieler bald nicht mehr, es mußten 32 sein. Damit konnte man dann schon recht anspruchsvolle Turniere verwalten.

Eine Weile später dann kam jemand auf die Idee, das ein simples K.O.-System doch unfair sei... Also strickten wir eine Hoffnungsrunde rein, so das man nun ein Spiel verlieren konnte, und doch noch das Turnier gewinnen. Das war dann aber für Turniere mit 32 Leuten oversized, also haben wir das Programm auf 64 Teilnehmer aufgeblasen, und in dem Zuge kriegten wir dann auch gleich eine Endrunde mit KO-System hin.

Bei dieser Masse an Leuten, wo die Turniere dann auch schon über 2 oder gar 3 Tage liefen, war eine Hoffnungsrunde dann wieder zu knapp und wir strickten eine zweite rein.

Als dann jemand auf uns zu kam und nach 128 Spielern fragte, mußten wir passen. Wir bekamen die ganzen Namen einfach nicht mehr in den Speicher rein. Die 64-Spieler-Version wurde noch wenigstens 5 Jahre auf verschiedenen Pool-Turnieren bundesweit eingesetzt. Dann kam die PC-Ära und die Leute haben sich dann lieber mit Excel abgequält.

Programmiert auf einem C64, alles in BASIC mit 38911 Bytes Speicher, Listings und Auswertungen wurden auf einem Commodore MPS801 (8-Nadel-Drucker, 50 Zeichen/s, keine Unterlängen), später dann einem Star NL-10 gedruckt.

26.07.2013 - 21:04 Uhr

Anders formuliert: Für den Compiler passen beide Methoden als Ziel für den Aufruf. Hilf ihm zu erkennen, was du willst, indem du einen typecast machst - so wie Chris es schon schrieb.

23.07.2013 - 15:41 Uhr

Würde ein zweidimensionales Array nicht auch gehen ?

float a[][] = new float[Rows][Cols];

oder so ähnlich 😉

18.01.2013 - 15:09 Uhr

Machtgier war das sicher nicht 😉 Aber Kostendruck. Es ist nun mal am einfachsten und extrem effektiv, einen deutschen Entwickler, der 240€/h kostet, zu feuern und dafür drei Programmierer in Indien einzustellen, die zusammen 10,50€/h kosten. Drei Leute brauchen ja nur ein drittel der Zeit für ein Projekt... Das die drei aber wenigstens ein dreiviertel Jahr brauchen, bis sie die Materie begriffen haben (Sprachbarriere ftw) und in dieser Zeit der deutsche schon 95% des Programms fertig hat, ist erst ganz allmählich bis in die Führungsetage vorgedrungen.

Als dann die Qualität der Arbeit zu erkennen war, hat mancher Entscheider seinen Fehler eingesehen.

18.01.2013 - 14:04 Uhr

Ach ja, die billigen Chinesen.

Hat meine damalige Firma auch gedacht und meinen Arbeitsplatz in die Ukraine outgesourced. Nach einem Jahr kam mein ehemaliger Boss wieder angekrochen wie ein geknüppelter Hund. Das projekt war nicht mal zu 30% fertig und nur ein Haufen wild zusammengeschmissener Programmcode, der nicht mal ansatzweise durchgetestet wurde.

Sicher, das hat nur 50% dessen gekostet, was ich verlangt hätte. Aber dafür hätte man auch 100% der Arbeit mit durchgetestetem Code bekommen. Nicht 30% mit zwei Bugs in jeder Codezeile.

Merke: Wer billig kauft, kauft zweimal. Das gilt ganz besonders in unserer Branche.

16.10.2011 - 23:15 Uhr

Wenn alles nix hilft, dann muß die Konfiguration eben in die Registry.

Wenn der Kunde derartige Anforderungen hat, muß er auch mit den Konsequenzen zurecht kommen und den überall verfügbaren Registry-Editor benutzen, um die Konfig zu erstellen.

20.05.2011 - 17:51 Uhr

@winsharp93: Meine Out-of-theBox-6870 kommt unter Vollast auf 91°C mit dem Standardkühler. Das ist noch weit weg von den Obergrenzen.

@Dux: Die Temperaturen sind - von der CPU abgesehen - völlig harmlos. Deine Graka langweilt sich übrigens 😁

Die CPU-Temperatur finde ich etwas hoch (Core0 und Core1 im Peak >60°C). Hier würde ich mal den Kühler genauer beäugen und vllt. auch mal die Wärmeleitpaste erneuern. Das dient aber mehr der Gesunderhaltung des Systems, kritisch sind die Temperaturen noch nicht.

19.05.2011 - 14:30 Uhr

Mit Verlaub, aber 75°C sind für eine Grafikkarte heutzutage ein Witz. NVidia gibt für seine Cores Maximaltemperaturen von 100-105°C an, ab denen sie das throtteln anfangen (das war damals für meine GT6600 schon so und gilt nach wie vor).

Anders ist das bei CPU, die sind sehr viel empfindlicher, da würden mich 75°C ausgesprochen nervös machen.

Wie dem auch sei, für mich klingt das ebenfalls nach einer thermischen Überlastung. Meist sind die Lüftungsschlitze des Gehäuses, die Rippen des Kühlers oder der ganze Kühlapparat einfach dicht mit Staub (in Raucherhaushalten setzen sich selbige fast fünfmal so schnell zu und sind dann kaum sauber zu bekommen - eigene Erfahrung). Bei Laptops, die schon vom Prinzip her ungeeignet sind für Spiele, ist das ganze aufgrund der sehr begrenzten Luftmengen noch erheblich kritischer.

19.05.2011 - 14:16 Uhr

Ich könnte mir vorstellen, das das mit Unicode zusammenhängt. Die von Google gelieferte XML-Datei ist womöglich ASCII codiert, durch dein simples einlesen und wieder wegschreiben wird das ganze nun aber Unicode-codiert abgelegt.

Ist allerdings pure Theorie.

19.05.2011 - 14:07 Uhr

Danke für die Hinweise, ich habe dank eurer Schubser eine passable Lösung gefunden.

  1. Man gebe dem NetworkStream einen ReadTimeout mit

  tcp.Connect(IPAddress.Parse(IP), Port);
  ns = tcp.GetStream();
  ns.ReadTimeout = 100; //100ms warten, nicht länger

Im Thread spielt sich das ganze dann unspektakulär ab:


int i;

try
{
  i = ns.ReadByte();
}
catch (IOException e)
{
  i = -2;
}
//i=-2 -> No Data available
//i=-1 -> Server weg
//Ansonsten steht im i unser erstes gelesenes Byte

Das wird mir schon mal ein ordentliches Stück weiterhelfen.

19.05.2011 - 12:41 Uhr

Von WCF hab ich hier schon allerhand gelesen. Allerdings finde ich in meinem C#-Compiler nicht die kleinste Spur davon. Da bräuchte ich nen kleinen Schubser in die passende Richtung. Dennoch bleibt meine Frage offen und an die C#-Profis hier gerichtet.

19.05.2011 - 12:20 Uhr

Hallo Freunde,

der Anfänger mal wieder 😁

Ich bastel gerade einen Client zusammen, der via TCP/IP mit einem Server kommuniziert. Die umherschwirrenden Daten haben nichts mit Web oder Internet zu tun. Ich benutze auf Clientseite den TcpClient.
Nachdem ich die üblichen Klippen umschifft habe (wie bastelt man Threads, was zur Hölle ist Invoke etcpp) möchte ich nun eine saubere Erkennung haben, das die Verbindung zum Server noch steht.

Das Problem daran ist nur: Wie ? Ich kann mich problemlos mit dem Server verbinden und alles funktioniert tadellos. Schließe ich aber den Server (ob nun ordentlich oder per Taskmanager), ist mein Client noch Stunden später der festen Überzeugung, der Server sei noch da. Bin ich vielleicht verwöhnt von Delphi und INDY10, wo so ein Disconnect sofort erkannt wird ? 🤔

Hier im Forum fand ich folgende Routine (war für ein direkt erzeugtes Socket-Objekt, sollte aber mit tcp.Client ebenso gut funktionieren)


try
{
   tcp.Client.Send(new byte[1], 0, 0);
   return true;
}
catch(SocketException e)
{
   return (e.NativeErrorCode == 10035);
}

die aber nicht recht funktioniert. Sobald nämlich einmal die Verbindung stand, liefert sie TRUE zurück, egal ob der Server noch da ist oder nicht.

Wo ist der Baum, der mir die Sicht auf den Wald versperrt ?(

02.05.2011 - 11:23 Uhr

Hallo Leute,

ich bin ein Frischling in C#, lerne es jetzt seit 6 Wochen. Mein erstes ernsthaftes Projekt (ein spezieller ASN.1-Parser) hat nun die 1200-Zeilen-Marke hinter sich und hier ist eine Frage aufgetaucht.

Als alteingesessener Delphi-Programmierer gibt es ja dieses clevere "in"-Konstrukt:

if MyVar in [1,6,8,15] then
[...]

Es würde mich nicht wundern, verfügte C# auch über so etwas - schließlich gibts da noch allerhand äußerst interessanter Konstrukte (z.B. Lambda-Ausdrücke, die ich aber noch nicht so recht durchstiegen habe).

Gibt es also so etwas (oder ähnliches) in C# und wenn ja, wie sieht sowas aus ?