Laden...

Forenbeiträge von Cuin Ingesamt 92 Beiträge

07.07.2010 - 09:27 Uhr

Da der letzte Beitrag schon etwas älter ist, stelle ich jetzt einfach mal eine Aufgabe^^


            byte i = 0x03;
            byte h = (++i & i++) == (--i & i--) ? i++ : ++i;
            Console.WriteLine("h ={0} | i = {1}", h, i); 

Wie lautet die Ausgabe? Natürlich sollte die Aufgabe im Kopf gelöst werden... Copy&Paste gilt nicht!^^

07.07.2010 - 08:44 Uhr

heißt das also, dass ich alle Daten verschlüsseln muss, bevor ich sie verschicke? oder gibt es da auch andere möglichkeiten.

-> Die Verwendung von Automatismen generiert Spielvorteile. (z.B. erhalst du einem Klick auf einen Button +1 Holz. Wenn jemand nun ein Programm schreibt, was 5000mal auf den Button klickt, dann hat er durch Automatismus einen Spielvorteil gewonnen)

Solche Programme muss man nicht mal selber schreiben... die gibt es schon (z.B.: IMacros)... in Kampf um Mittelerde muss man z.b., wenn man effektiv Truppenausbilden will, in ALLEN Städten von JEDEM Typ eine genau berechnete Anzahl an Einheiten pushen... viele nehmen dazu IMacros her... d.h. sie nehmen ihre Aktionen in der ersten stadt auf... dann klicken sie auf die nächste stadt und spielen ihr aufgenommenes Programm wieder ab...
Meine Meinung (und auch Meinung des spielentwicklers): das ist nicht besonders schlimm, da der User keinen entscheidenden Spielvorteil erlangt, sondern nur etwas Zeit und Arbeit spart... (Sagen wir mal 3 mal pro tag in 26 städten 10 Einheitentypen ausbilden... = 780 Zahlen eingeben pro tag.... und ein BG soll ja ein spiel sein... und keine arbeit...) anders schaut es bei dem aufleveln der gebäude aus: da nicht jede stadt gleich weit entwickelt ist und gleich viele rohstoffe hat, kann man imacros nur in seltenen fällen zum gebäude-aufleveln einsetzten...

Also von den 3 oben genannte problemen sehe ich nur die ersten beiden als kritisch an... die man aber, wie du schon sagtest, vermeiden kann...

aja, worüber ich mir auch noch gedanken gemacht habe: Das spiel sollte auch gut für "gelegenheitsspieler" geeignet sein. d.h. es sollte reichen, 1-2 mal am tag reinzuschauen um gut voran zu kommen... allerdings sollte man sich auch länger mit dem spiel beschäftigen können, wenn man gerade lust dazu hat... (z.b. durch kämpfe oder Entwicklung neuer Kampftechniken oder allianzkriege etc.)

Ich meine damit, dass man nicht 24 h am tag an dem spiel sitzen kann, wie bei einem normalen pc-spiel... aber auch nicht zwischen jeder handlung 2 h warten muss... ich glaube, dass wird nicht leicht sein dies umzusetzten...
Die Rangliste sollte also nicht von "Suchties" dominiert werden, also Leuten die ständig on sind, sondern von Spielern, die die beste Taktik ausgedacht haben etc.

06.07.2010 - 16:38 Uhr

ok, das gefällt mir auch schon viel besser, wenn ALLE Daten im server gespeichert und berechnet werde...

ne, an sich wird das spiel nicht viel zu rechnen habe denke ich mal... lediglich die kampfberechnungen werden aufwendig sein.... und diese finden ja nicht kontinuirlich statt (wie bei age of empires)
Was ist den mit die Stämme? Gabs dort manipulationen im spiel? Bin dort leider nicht angemeldet... Kampf um Mittelerde kennt ihr nicht zufälligerweise?

06.07.2010 - 16:22 Uhr

Achso... jetzt verstehe ich das ganze so langsam^^

So habe ich es mir eigentlich auch vorgestellt, also dass der Server die Daten berechnet und dann dem Clienten nur noch zur ausgabe schickt...

gut gut... jetzt habe ich schon viele anhaltspunkte für mein projekt...

Wenn eine seite aktualisiert wird, wird erst nachgeschaut ob evtl. angekommene truppenbewegungen zu berechnen sind etc. und die ergebnisse dann ausgegeben. bei einer kampfanimationen wie ich sie vorhin erläutert habe, muss der dienst halt jede sekunde aufgerufen werden... mit ajax sollte das ja glaube ich kein problem sein (dank ajax wird ja nicht jedesmal die ganze seite neu geladen, sondern nur z.b. die lebenspunkte aktualisiert oder?)

06.07.2010 - 16:11 Uhr

@MarsStein: Da hast du Recht.... die Daten müssen ja nur neu berechnet werden, wenn sie jemand braucht. Dann werde ich versuchen, das mit nem Service im hintergrund laufen zu lassen... allerdings stellt sich mir da die frage, wo der Service laufen soll? wenn er beim clienten läuft, dann besteht ja die Gefahr, dass die Daten manipuliert werden können oder?

@Phönix: Was heißt den Echtzeitstrategei eigentlich?^^ Es ist eher so, dass man sein Heer aufbaut und dann irgendjemand angreift (entweder Truppenbewegunge die dann irgendwann ankommt oder arena wo der kampf sofort startet) sobald der kampf startet, sieht man nur noch die "kampfanimation" d.h. wie die lebenspunkte runde für runde neuberechnet werden. sagen wir mal ein kampf dauert 12 sekunden, d.h. dann, dass der user 12 sekunden lang nix machen kann, aber die daten trotzdem "in Echtzeit" ausgegeben werden... wie handhabe ich sowas am besten?
Meine idee: kurz vor dem kampf werden alle nötigen Daten zum clienten geschickt, dann wird der kampf gestartet und alle werte runde für runde neu berechnet und ausgegeben und danach die daten dem server zugeschickt??? das wird wohl nicht ganz klappen vermute ich mal^^

06.07.2010 - 15:01 Uhr

Ok, dankeschön^^

Also, vllt bin ich ja ein wenig größenwahnsinnig, denn das Spiel wird ein ziemlich komplexes kampfsystem haben. Es wird darum gehen, die beste Truppenkonstillation herauszufinden. D.h. es wird sehr viele verschiedene Truppenarten geben. Also auf jedenfall ein Strategiespiel... keine wirtschaftssimulation und keine rpg.... Natürlich stehen einem Spieler nicht gleich von anfang an alle Truppen zur verfügung. 😃

Ranglisten etc. sollen einmal pro Stunde aktualisiert werden.

An der Visualisierung des Kampfsystems, sowie am Kampfsystem selber muss ich noch arbeiten. Es wird aber wahrscheinlich so ähnlich wie bei Gondal ablaufen. d.h. rundenbasiertes verteilen der kampfschäden. eine runde soll 1 sekunde dauern... der user kann das kampfgeschehen selber nicht beeinflussen... er kann nur zugucken^^ allerdings kann er vor einem kampf "zahlreiche" optionen einstellen, wie er den Kampf kämpfen will...
Das KS hört sich jetzt vllt n bisschen langweilig an... aber ich will ja nicht gleich alles verraten, sondern lediglich das grobe prinzip offen legen^^

D.h. also, dass jede sekunde (während des kampfes) die Daten an den Server geschickt werden, die Daten manipuliert werden und schließlich zeitnah visualisiert werden (vllt sogar mit kleinen animationen).

außerdem soll es noch items geben... bisher sollen diese jedoch nur außerhalb eines kampfes einsetzbar sein.
eine karte wird es auch geben in der man sich frei bewegen kann... evtl. mit maximalen "schritten" pro tag/stunde etc. Die karte an sich wird gerastert sein und jede zelle mit einem kleinen bildchen versehen (z.b. berge, hügel etc.)
ob und wie spieler angezeigt werde, die sich in unmittelnaher umgebung befinden muss ich mir noch überlegen.

Der Avatar selber kann nicht besonders beeinflusst werden... (nur wenige eigenschaften)...

also der schwerpunkt liegt auf das kampfsystem.

hmm... im moment fällt mir nix mehr ein, was für euch noch interessant sein könnte^^

aja, vllt noch, dass die meisten daten nur bei einem neuladen der seite aktualisiert werden... einige dinge sollten allerdings mit javascript oder so ständig aktualisiert werden.... (z.b. server uhrzeit etc.)

Aber was Tomot meinte ist, dass das Spiel ja jede Sekunde was macht. Sei es Einheiten sammeln lassen oder wandern. Für diese Sachen muss ja natürlich eine Anwendung auf dem Server laufen, die die Spieldaten aus der Datenbank holt, nach entsprechender Zeit verändert und wieder abspeichert.

könnte man das spiel evtl. so realisieren, dass, wenn man eine truppenbewegung startet, nur die Zeit gespeichert wird, bei der die truppen ankommen und wenn diese zeit erreicht wird, wird ein event oder so gefeuert, wodurch dann der aktuelle stand berechnet wird? Den während die truppen unterwegs sind, kann man sie eh nicht angreifen...

06.07.2010 - 12:01 Uhr

@Phönix: Stimmt eigentlich^^ Ich kann mir ja schon die neue Version runterladen... dann werde ich das wohl als erstes machen 😃

Das mit dem Backgroundservice finde ich für den Anfang etwas schwer. Es reicht zu Beginn auch wenn du auf deiner Seite einen Login für den administrativen Bereich machst. Wenn du dann später das Spiel unter die Massen verteilen willst sollte man natürlich den normalen Benutzerzugang und den Adminzugang nicht gerade auf der selben Seite machen.

Das verstehe ich nicht so ganz. Was hat ein Backgroundservice mit einem Login zu tun? Meinst du mit Backgroundservice das hier: http://de.wikipedia.org/wiki/Background_Intelligent_Transfer_Service oder etwas anderes? Ein Adminzugang dient doch lediglich der Spielkontrolle oder? Also beim fertigen Spiel?

06.07.2010 - 10:17 Uhr

Erstmal vielen Dank für eure Tipps. 😃

@Phönix: Da ich im moment noch Student bin, habe ich kostenlosen Zugriff auf einige Microsoft-Produkte. Ich sollte mal ein wenig googeln, welche Version von VS 08 für welche Zwecke gut sind. Man kann ja nämlich (so weit ich weiß) auch mit der "normallen" VS 08 Version eine asp.net- bzw. Webanwendung erstellen oder? Oder unterscheiden sich die Versionen lediglich um einige zusatzfunktionen wie z.B.: Css- oder Htmleditor?

@Tomot:

Vermeide also im Browsergame und in dem Service zweimal den gleichen Code zu schreiben, das führt nur zu Problemen. Da ist der genannte DLL Ansatz besser.

Das verstehe ich nicht so ganz. Meinst du damit, dass z.b. die Berechnungen der resourcen immer entweded im Browsergame oder im Service stattfinden soll?

Da kommt mir auch gleich eine Frage auf: Welche Berechnungen kann man im Browsergame laufen lassen und welche sollte man im Server verarbeiten? Gibt es da irgenwelche Ansatzpunkte, oder kann man das beliebig machen?
So wie ich das jetzt verstehe: Wenn ich z.b. ALLES im Server berechnen lassen will, dann entsteht dadurch ein hoher Traffic, da ja der Server die aktuellen Werte vom clienten abholen muss etc.
Wenn ich aber sehr vieles im Clienten berechnen lasse... was hat das für nachteile?

Ok, auf Anhieb würde ich jetzt sagen, dass z.b. die Resourcen des Spielers im Server berechnet werden, da diese ja so oder so in der Datenbank abgelegt werden müssen... die berechnung eines Kampfschadens kann im Clienten berechnet werden, das resulat muss aber danach dem server mitgeteilt werden...

Je mehr Berechnungen ich allerdings dem Clienten überlasse, desto länger braucht man zum laden der einzelnen seiten oder? Verstehe ich das so richtig?

06.07.2010 - 09:45 Uhr

Schon interessant zu wissen, wie andere Leute sich fit halten... was mir beim durchlesen der Beiträge aufgefallen ist, ist, dass ein unerwartet großer Anteil der Benutzer einer Sportart nachgehen, die sich deutlich von den üblichen Sportarten (z.B.: Fussball, Joggen, Fitness etc. ) abheben bzw. die nicht so verbreitet sind.

Find ich gut ^^

05.07.2010 - 16:51 Uhr

Eigentlich nicht.

Dann hab ich mich wohl verhört^^ Wäre ja auch zu schön um war zu sein.
Ok, dann werd ich mich wohl noch informieren müssen, wie ich so einen webserver installieren/aktivieren kann... danke für eure antworten.

05.07.2010 - 16:42 Uhr

Das ist doch dieser Militante Verein der die Nahkampftechniken des Isrelischen Militärs lehrt?
Also bei uns in der Gegend haben die keinen besonders guten Ruf.

@mo#: Aus welcher gegend kommst du den ugnefähr? (Bundesland genügt mir)

Habe zwar noch nie was von Krav Mage gehört, allerdings scheinen mir Selbstverteidigungs-Kampfarten nicht schlimm zu sein. Solange man sie auch nur für die selbstverteidigung oder zum fithalten benutzt.^^

Bei uns in der Gegend (Bayern/Schwaben) ist Ju-Jutsu total in. Habt ihr schonmal von KIBOTU gehört? (KInderBOdenTUrnen xD)

05.07.2010 - 16:25 Uhr

ok, das hört sich schonmal gut an, dankeschön^^

Sobald ich mit meinen Kenntnissen in ASP.net so weit bin, dass ich loslegen kann, werd ich mir das mit dem lokalen Server dann mal anschauen... aber ich glaube mal irgenwo gehört zu haben, dass man bei VS 08 automatisch einen webserver dabei hat...? kann das sein?

[Edit]Das habe ich grade im Inet gefunden: "Stellen Sie sicher, dass die Internet-Informationsdienste (IIS) installiert sind. Wenn nicht, dann installieren Sie die IIS. Auf diese Weise verfügen Sie über einen lokalen Webserver, der Ihre ASP.NET-Seiten ausführen kann."

Ist diese Information noch aktuell oder schon veraltet???[/Edit]

05.07.2010 - 14:02 Uhr

Hallo Phönix,

erstmal vielen Dank für deine ausführliche und hilfreiche Antwort. Den Ansatz, das Spiel erstmal vollständig auf HTML aufzubauen, find ich gut. Ich werde es vermutlich auch so machen.
Da das Spielprinzip noch nicht ganz ausgereift ist, werde ich wohl zunächst einige Testprogramme schreiben müssen, um überhaupt mal irgendwas im Browser anzeigen zu können.

Was ich mich allerdings jetzt noch frage, ist, wie das mit dem Server und Datenbanken funktioniert. Wie lange kann ich von meinem Laptop mit Internetverbindung an dem Spiel programmieren ohne "online" zugehen, also ohne einen Server zu kaufen bzw. zu mieten?
Wenn ich mit VS 08 programmiere, wird dann dort ein Server simuliert? Die Frage hört sich vielleicht jetzt dumm an, aber mir fehlt hierzu irgenwie noch das grundlegende Verständnis...

05.07.2010 - 10:00 Uhr

Hallo Leute,

ich habe für die nächste Zeit vor ein neuartiges Browsergame zu erstellen.
Doch leider fehlen mir hierbei die Ansätze, in was ich mich einarbeiten soll.

Um Antworten wie "Das schaffst du nie" oder "Lern erstmal html" vorzubeugen:
Mir ist bewusst, dass mein Kenntnisstand im moment nicht grade der höchste ist, dass ich für das Projekt 1-2 Jahre einplanen kann, dass auf mich Kosten im 3-4 stelligen Bereich zukommen werden und dass ich mich in einige Themengebiete einarbeiten muss.

Wieso ich das ganze trotzdem machen möchte:

  • weil ich mich für C# begeistern habe lassen, und das BG in dieser Sprache schreiben möchte.

  • weil mich die Technologie interessiert die dahinter steckt (Server, Datenbanken etc.)

  • weil mir generel programmieren spaß macht (programmiere schon seit der 7. Klasse (Basic,rpg-maker etc.))

  • und weil es auch im Lebenslauf sinnvoll ist, auf Kenntnisse hinweisen zu können, die man sich nicht im Verlauf des Studium angeeignet hat.

Das BG soll eine art "tabellen-BG" werden, also ohne 3D-technik oder videos. Im prinzip sowas wie die Stämme etc., allerdings mit einem ganz anderen spielprinzip.

Was ich kann:

  • C
  • C#
  • bisschen javascript
  • bisschen flash
  • fundierte html kenntnisse
  • fundierte css kenntnisse

Und jetzt die Frage: habt ihr vllt tipps für mich, wie ich das ganze angehen soll? Also damit ich nicht gleich von anfang an in die falsche richtung gehe bzw. mich in die falschen themengebiete einarbeite. Ich habe schon ein wenig gegoogelt, doch leider sind viele BG's in php geschrieben. Aber das muss doch auch in C# gehen oder? Funktioniert das mit WPF???

Bin für jeden Hilfreichen Tipp oder Verweis auf anderen webseiten dankbar! Sehr hilfreich wären auch aufzählungen, was unbedingt für ein BG erforderlich ist und welche zusatztechnologien man benutzen kann, die in welcher hinsicht auch immer, das BG verbessern können.

[Edit]ok, meine weiteren reserchen ergaben, dass ich das BG am besten mit asp.net, sql und evtl. ajax realisieren werde. ist der Ansatz ok?[/Edit]

02.07.2010 - 08:41 Uhr

@gfoidl: Wow. respekt^^
Sowas muss man erstmal schaffen....^^

Ich glaube, dass du genug sport machst 😄

01.07.2010 - 16:30 Uhr

das war eine gute idee mit dem Exception-Block...
habe auch schon öfter fehlermeldungen im "invoke-Block" bekommen, aber dann erst ewig suchen müssen, wo genau sich der Fehler befindet....

vllt hilft mir deine Idee in Zukunft ja auch, den Fehler schneller finden zu können^^

01.07.2010 - 15:13 Uhr

Solch Trennstriche halte ich total störend - zumal man durch die Dokumentationskommentare ja eine m.E. ausreichende Trennung hat.

Ok, hört sich sinnvoll an.... außer man hat viele Methoden, die man nicht bespreiben muss, weil sie selbstbeschreibend sind (z.b. events, ButtonClick usw.)
Und dann verliert man schnell den Überblick, wenn man zwischen den Methoden hin und her springen muss... ging mir jedenfalls so bisher....
Deshalb habe ich auch die Trennstricke gemacht, damit ich mich besser zurecht finde...

Ich selber habe die XML-Dokumentation noch nicht benötigt. In meiner derzeitigen Firma (mache praktikum) gibt es auch keine C#-Richtlinien, die gibt es nur für C, weil wir fast nur in C programmieren (Embedded Systems)....

das mit den regions hab ich schon kapiert^^ hat vor und nachteile... ich benutze sie um den für die weitere Entwicklung unbenötigten Code wegzublenden...^^

01.07.2010 - 13:23 Uhr

Das sind schon mal viele gute tipps dabei^^

habe das mit den regions noch garnicht gewusst, wofür die da sind... benutze sie jetzt auch in meine programm^^ danke für die hinweise....

01.07.2010 - 12:15 Uhr

@tom-essen: ne, dafür braucht man keine speziellen Reifen^^ Wenn ich in den Semesterferien meinem Ferienjob nachgehe, dann fahre ich auch meistens bei Wind und Wetter mit dem Fahrrad. Schnee ist garnicht so schlimm... jedenfalls nicht so schlimm wie heftiger Regen bei Gegenwind und auch noch auf einem Fahrradweg an einer Landstraße... sowas macht kein Spaß!
Früher musste ich auch bei Schneefall Zeitungen austragen... das ist garnicht so schlimm wie viele denken... allerdings würde ich "zum Spaß" bei solch einem wetter auch net grade rausgehen.... da trainiere ich lieber daheim im trockenen....

01.07.2010 - 12:03 Uhr

Hallo Leute,

ich wollte geren wissen, wie ihr euren fertigen Files aufpeppt. D.h. wo, wie und in welchem Umfang benutzt ihr "Nichtkommentierende Kommentare".

Darunter verstehe ich z.b.:

//==============================================================================

oder

//------------------------------------------------------------------------------

Oder z.b. das Umrahmen von "Überschriften" oder Abschnitten z.B.:

        // ***************************
        // Public Methoden
        // ***************************

oder

/* 
 * Das ist ein
 * mehrzeiliger
 * Kommentar
 */

Was mit besonders gefällt und ich hier schon öfter gesehen habe war die Trennung der Methoden mittels:


        //==============================================================================
        private void myScrollBar_ValueChanged(object sender, EventArgs e)
        {
            ZeileFokusieren(myScrollBar.Value);
        }

        //==============================================================================
        private void ZeileFokusieren(int Scrollwert)
        {
            dataGridView1.FirstDisplayedScrollingRowIndex = Scrollwert;
        }

Mittlerweile trenne ich fast alle meine Methoden mit so einem Strich.

Manchmal kommt es aber vor, dass man in einer File mehrere Methoden hat, die man gruppieren kann... aber wie trennt man jetzt solche Gruppen optisch von einander?

Bisher mach ich das so:


        //*****************************************************************************
        // Die Threads:
        // *****************************************************************************

Wann benutzt ihr für EINZEILIGE Kommentare diesen Kommentar

// Kommentar

und wann diesen:

/* Kommentar */

Ich befinde mich zurzeit noch bei der Suche nach dem "besten Style"...
d.h.: Optisch ansprechend, strukturierend, aber auch nicht "overdressed"

Benutzt ihr immer den gleichen Style? Oder kommentiert ihr nach Lust und Laune?

Und noch was: Deklariert ihr alle globalen Variablen immer am anfang der Klasse oder vor den Methodenblöcke die damit arbeiten?

01.07.2010 - 11:33 Uhr

Ja, das ist sicher gut, wenn man mit dem Fahrrad zur Arbeit und zum Einkaufen etc. fahren kann...
Aber als Landbewohner geht das leider nicht immer... dummerweise sind bei meinen bisherigen Wohnungen die Supermärkte entweder auf der anderen Straßenseite oder aber direkt nebem der Firma gewesen, d.h. ich musste maximal 3 minuten laufen... und von der Wohnung bis zur Firma gehts leider auch nur mit dem Auto....

ich gehe seit ca. 2 Jahren gerne Abends spazieren - auch im Winter - das tut ziemlich gut...^^

Wenn wir schon gerade bei dem Thema sind: Was ist besser: 5 Minuten zu Fuß gehen, oder 5 Minuten Fahrrad fahren?

01.07.2010 - 10:35 Uhr

Im Vergleich zu euch mache ich ja fast nix^^

In der 10ten Klasse musste ich bei einer Kreismeisterschaft einen 1000 Meter-Lauf machen... - als Vertreter meiner Schule -

Ca. 4 jahre Später habe ich mal wieder Fussball gespielt... nach 2 mal 8 Minuten Spielzeit war ich sowas von total erschöpft, dass ich mich nur noch auf dem Boden hinlegen konnte und hoffen, dass ich net gleich erbrechen muss... seit dem weiß ich, dass es ohne Sport nicht geht... vor allem nicht in diesem Berufszweig...

01.07.2010 - 09:15 Uhr

Da wohl die meisten von hier den großteil des Tages am PC sitzen wollte ich mich mal erkundigen, wie ihr euch so fit haltet?

Ich bin zurzeit noch im Studium und bei mir fangen jetzt schon Rückenschmerzen etc. an. Bin mal ne Zeitlang in Fitnesscenter gegangen... habe aber damit aufgehört weil ich einfach keine Zeit (und Lust) habe da 3-4 mal in der Woche hinzulatschen...

Habe mir deshalb Hanteln zugelegt um die Rückenmuskelatur und den rest des oberkörpers zu trainieren... und werde demnächst mit joggen anfangen...

was macht ihr so? oder habt ihr keine Beschwerden?

29.06.2010 - 13:38 Uhr

Das wäre in der Tat eine mögliche Lösung^^

Allerdings würde dadurch der senkrechte Strich, der sich immer ganz rechts im header der letzten Spalte befindet, nicht mehr auftauchen, was auch nicht so optimal ist... soll ja natürlich profesionell ausschauen, auch wenn es das nicht ist^^
Will ja auch deswegen die SB nicht rechts neben dem DGV platzieren, weil man dadurch erkennen kann, dass es sich um eine eigene SB handelt....

Gibt es den keine ähnliche methode wie die vorhin genannte für DG?

29.06.2010 - 12:05 Uhr

Hallo alle zusammen,

ich habe folgendes Problem:

ich möchte, dass sich die Breite der letzten Spalte meines DataGridViews automatisch an den noch verfügbaren Platz anpasst. Da ich jedoch meine eigene VScrollbar eingebaut habe, ist der verfügbare Platz nicht mehr die Breite des DGV's sondern die Breite des DGV's minus die Breite der Scrollbar. "Fill" funktioniert also leider nicht mehr, weil sich dadurch der Inhalt der letzten Spalte unter umständen hinter die VScrollbar schieben kann und dadurch unlesbar wird.

Für ein Datagrid (DATAGRID nicht DATAGRIDVIEW) gibt es solch einen Befehl:

DataGrid.MaxColumnWidth-Eigenschaft

ich bräuchte sowas in der art für DataGridView, sodass sich die breite meiner spalten automatisch an eine von mir selber definierte maximale Breite anpassen kann. Bis jetzt habe ich mit statischen breitenangaben gearbeitet. Ich könnte natürlich auch einfach die Scrollbar neben dem DGV anstatt auf dem DGV platzieren, das schaut aber net so gut aus...

Hat jemand eine Idee?

22.06.2010 - 13:20 Uhr

Stimmt^^ Es heißt ResetItem, da es aber kein resetitems gibt, ist das auch wieder egal^^ Ich habe ResetItem() gemeint 😃

ja, es muss ja auch nur ein Datenpaket (bzw. eine Zeile) pro aufruf ausgegeben werden...

mit Resetbindings(); wird ja die ganze Datasource resetet, obwohl nur EIN element dazugekommen ist, deswegen sollte eigentlich Resetitem() den gleichen effekt haben, bloss dass der "fokus" nicht auf die erste zeile springt...

aber leider tut sich da nix... ich habe jetzt mal ne eigene scrollbar hinzugefügt, die auch auf die maus_wheel events reagiert... damit habe ich zumindest die anderen ungewünschten eigenschaften beseitigen können...

das einzige problem ist jetzt nur noch, dass das DGV bisschen flackert...

PS: der versuch mit der OnCellValueNeeded-Methode hat nicht hingehauen...

22.06.2010 - 10:27 Uhr

ja klar, ich rufe resetitems ja auch jedesmal auf, sobald ich eine Datenpaket empfangen habe. Aber leider ist das meinem DGV irgendwie egal....

ich versuche grade den sprung auf die erste Zeile abzufangen, indem ich bevor ich resetbindings auslöse eine boolvariable setze und dann irgendwie in der OnCellValueNeeded-Methode den Sprung verhindere.... mal sehen ob das klappt

22.06.2010 - 09:45 Uhr

Ja, die BindingList hat im Versuch versagt... das DGV ist irgendwann mit dem zeichnen nicht mehr hinterher gekommen, sodass der zwischenpuffer kontinuirlich gewachsen ist... (was auch nicht sinn der sache ist, die Daten sollen ja schließlich zeitnah ausgegeben werden)

resetitems hat leider nix gebracht... es wird nur noch die erste Zeile ausgegeben (wegen dem if(InitInvoke)-Block, der die Datasource vom DGV festlegt und damit die methode resetbindings auslöst) habe es mit:

bs.ResetItem(bs.Count); 

versucht und allen möglichen Befehlen wie z.B.:


                    dataGridView1.Invalidate(true);
                    dataGridView1.Refresh();
                    dataGridView1.Update();

Kann man vllt irgendwie das DGV einfrieren lassen solange ich

bs.ResetBindings(false);

und

dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1 

ausführe?

21.06.2010 - 15:11 Uhr

Ich habe jetzt mal meine List durch eine Bindinglist ersetzt...

anstatt

bs.ResetBindings(false);

benutze ich jetzt:

Q.Datenbank.Add(obj);

Der Übergabeparameter der methode ist jetzt nicht mehr string[] sondern StringObjekt.

Das klappt alles ganz wunderbar, doch vermute ich, dass durch die Bindinglist der Virtuelle Modus keine Funktion mehr hat.
Bin grade am testen, ob die CPU-Auslastung mit steigender Anzahl steigt oder nicht...

[EDIT]
Wie vermutet kommt die Ausgabe nicht mehr hinterher, wodurch mein Zwischenspeicher ins undendliche wächst 😦

@ErfinderDesRades: wenn ich "bs.ResetBindings(false);" durch "bs.ResetItem(bs.Count);" gibt mein DGV nur eine Zeile aus 😦 obwohl bs.Count steigt.

Kennt jemand von euch das Event, dass im DGV auftritt, sobald sich der FirstDisplayedScrollingRowIndex geändert hat? Dadurch könnte ich nämlich den Sprung auf die Erste Zeile nach einem reset verhindern...
[/EDIT]

21.06.2010 - 11:00 Uhr

Also das war so:

Ich habe resetbindings durch refresh ersetzt. Folge:
Mein DGV hat nur noch eine Zeile ausgegeben, danach war schluss...

dann habe ich folgende Zeilen aus dem if(InitInvoke)-Block rausgenommen, sodass sie bei jedem aufruf der methode behandelt werden:

                bs.DataSource = Q.Datenbank;
                dataGridView1.DataSource = bs;

Folge: jetzt werden wieder alle Daten angzeigt, doch der index springt nach refresh() wieder auf zeile 0...

SuspendLayout funktioniert schon, nur bezieht sich dass auf Größenänderungen von Controls. Dein Grid soll aber doch seine Abmaße nicht ändern, odr?

ich dachte Suspenlayout wäre dafür gedacht, wenn irgendetwas neu gezeichnet werden soll (z.b. mehrere zeilen aufeinmal, anstatt einzelne zeilen hintereinander)
Um deine Frage zu beantworten: nein, es ändert sich nur der inhalt und evtl. die hintergrundfarbe der zeile

Wäre es sinnvoll, anstatt der Variable "Zeilenmerker" einfach den Wert der scrollbar zu nehmen? Falls ja, wie kann man den Wert abholen?? o_O

hat jemand eine idee, wie man den wert der scrollbar abfragen kann? Würde diese option nämlich gerne ausprobieren....

[EDIT]
Nur so nebenbei:

Das hier habe ich grade bei MSDN gefunden:

ResetBindings is automatically called whenever another member makes major changes to the data-binding, such as setting the DataSource or DataMember properties. However, the programmer can also call this method explicitly.

Das erklärt auch, wieso diese beiden Zeilen etwas bei der Ausgabe bewirken, wenn sie bei JEDEM methodenaufruf durchgeführt werden:


                bs.DataSource = Q.Datenbank;
                dataGridView1.DataSource = bs;

[/EDIT]

21.06.2010 - 10:08 Uhr

Bei DGV.Refresh() springt der Fokus leider ebenfalls auf die erste Zeile 😦

SuspendLayout/ResumeLayout hat hier imo keine Funktion.

Das gleiche habe ich mir irgendwie auch schon gedacht... denn, andernfalls würde ja die datasource erst reset, dann der fokus gesetzt und DANN erst neu gezeichnet, wodurch der Fokus nicht auf die erste zeile gesprungen wäre....

gibt es da einen Grund dafür wieso SuspendLayout/ResumeLayout nicht funktioniert? Und gibt es evtl. eine Ersatzmethode?

Was mir grade noch so einfällt:

Wäre es sinnvoll, anstatt der Variable "Zeilenmerker" einfach den Wert der scrollbar zu nehmen? Falls ja, wie kann man den Wert abholen?? o_O

21.06.2010 - 09:04 Uhr

Hallo Leute,

ich habe da ein Problem bei der Fokusierung der aktuell angezeigten Zeile im DGV.
Und zwar springt der Wert des "dataGridView1.FirstDisplayedScrollingRowIndex" auf 0, wenn ich die datasource des DGV mittels "bs.ResetBindings(false);" resete:
An sich ist das ja kein Problem, weil ich in meiner Methode den index der vor dem Reset angezeigten Zeile zwischenspeichere und nach dem Reset den "dataGridView1.FirstDisplayedScrollingRowIndex" wieder auf den gespeicherten Wert setze.
Das Problem ist, dass die horziontale Scrollbar durch das ständige hin und herspringen des "dataGridView1.FirstDisplayedScrollingRowIndex" quasi blockiert ist.
Außerdem flackert die Anzeige dadurch ein ganz kleines bisschen, was auch net so toll ist.
Hat jemand eine idee, wie man dieses Problem umgehen kann, ohne dass ich mein ganzes Programm umschreiben muss? (Möchte die aktualisierung des DGV mittels "bs.ResetBindings(false);" eigentlich nicht aufgeben, wer wissen möchte warum -> [gelöst] Probleme bei der Kommunikation zwischen GUI und Thread)


        //==============================================================================
        void ZeileAnzeigen(string[] sRowBuffer)
        {
            if (dataGridView1.InvokeRequired)
            { // Wenn Invoke nötig ist, ...
                // dann rufen wir die Methode selbst per Invoke auf
                this.Invoke(new ZeileAnzeigenDelegate(ZeileAnzeigen), new object[] { sRowBuffer });
                return;
            }
            //eigentlicher Zugriff; läuft jetzt auf jeden Fall im GUI-Thread

            if (InitInvoke)
            {
                InitInvoke = false;

                dataGridView1.VirtualMode = true;
                dataGridView1.ReadOnly = true;
                dataGridView1.AllowUserToAddRows = false;
                dataGridView1.AllowUserToDeleteRows = false;
                dataGridView1.AutoGenerateColumns = false;

                bs.DataSource = Datenbank;
                dataGridView1.DataSource = bs;
            }

            lock (this)
            {
                SuspendLayout();
                Zeilenmerker = dataGridView1.FirstDisplayedScrollingRowIndex;

                if (queuebuffer.Count > 100)
                {
                    ChangeAusgabe = true;
                }

                if (ChangeAusgabe)
                {
                    if (AusgabeZeilen >= 12)
                    {
                        bs.ResetBindings(false);
                        AusgabeZeilen = 0;
                    }
                    else
                    {
                        AusgabeZeilen++;
                    }
                }
                else
                {
                    bs.ResetBindings(false);
                }

                if (!BusMonPause && queuebuffer.Count < 100)
                {
                    dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;
                }
                else
                {
                    //Da der Fokus nach "bs.ResetBindings(false);" auf die erste Zeile springt,
                    //diesen wieder auf die aktuell angesehene Zeile springen lassen:
                    dataGridView1.FirstDisplayedScrollingRowIndex = Zeilenmerker;
                }

                ResumeLayout();
            }
16.06.2010 - 14:52 Uhr

@ErfinderDesRades: Vielen Dank für deine Tipps und Hinweise^^ (PS: hast einen coolen Avatar^^)

Ah, deinen Datenklassen-Code kannstenoch vereinfachen, mittels autom Properties:

Gut zu wissen^^

übrigens, "m_data" ist ein unmöglicher Name für ein public zugreifbares Feld. Wenn überhaupt(!!), sollte das Feld "GridData" oder so heißen, und readonly deklariert sein.

Diese Codezeilen habe ich aus irgendeinem PDF-Buch rauskopiert^^
Ich bin ziemlich neu in C# und verstehe noch net so ganz wann eine methode/variable public oder private sein soll...

Leider habe ich mich zu früh gefreut... der Fehler taucht jetzt erst bei der 170.000 Zeile auf 😦

ABER: ich habe den Fehler jetzt endgültig beseitigen können!

Problem war, dass die Daten sobald sie im Messagehandler angekommen sind zwischengespeichert wurden und dann der 1.Thread (Einlesethread) gestartet wurde, der das Datenpaket bearbeitet und die einzelnen Befehle dem 2.Thread (Ausgabethread) zugeschickt hat.


rxString = System.Text.ASCIIEncoding.ASCII.GetString(pSocket.GetRawBuffer, 0, iNbrOfBytes);
DataReceivedEvent.Set();

Was ich die ganze Zeit versucht habe, war, die Ausgabe schneller zu machen! Wodurch sich das Problem lediglich verschoben hat, aber nicht beseitigt wurde!
Denn durch das Einlesen und Ausgeben wurde rxString einfach durch die neuen Daten überschrieben, wodurch sich der Datenverlust erklären lässt!

Mein Problem, das ich 2 Wochen lang versucht habe zu lösen, wurde durch folgende Zeilen beseitigt:

rxString += ... // "+=" anstatt nur "="

und dem "löschen des Strings sobald ich ihn zum Verarbeiten weitergegeben habe:

rxString = "";

Naja, dafür habe ich viel zum Thema Datagridview, Threads, Virtual Mode, Events und DataSource gelernt^^ Bin eigentlich C Programmierer (hardwarenah) und beschäftige mich seit ca. 4 Monaten im Rahmen meines Praktikums mit C#.

Vielen Dank nochmal für eure Hilfe!

15.06.2010 - 10:04 Uhr

@ErfinderDesRades: ja, mein konzept hatte noch ein paar Mängel^^ Das mit den 1000 Zeilen wäre aber trotzdem nötig gewesen, da die meisten Befehle ständig wieder kommen und nur z.b. jeder hundertste Befehl und dessen Position interessant ist....

So, erstmal vielen Dank für eure Tipps und Ratschläge. Ich schaffe es mittlerweile ohne Fehlermeldungen auf über 100.000 Zeilen zu kommen, d.h. das Einlesen und Ausgeben funktioniert jetzt 😄

Habe das Problem folgendermaßen gelöst:


                dataGridView1.VirtualMode = true;
                dataGridView1.ReadOnly = true;
                dataGridView1.AllowUserToAddRows = false;
                dataGridView1.AllowUserToDeleteRows = false;

                public List<StringObjekt> m_data = new List<StringObjekt>();
                BindingSource bs = new BindingSource();
                bs.DataSource = m_data;
                dataGridView1.DataSource = bs;

//aktualisiert wird das DGV über diesen Befehl:
bs.ResetBindings(false);

private void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
        {

            
            if (e.ColumnIndex == 0)
            {
                e.Value = m_data[e.RowIndex].Zeile;
            }
            else if (e.ColumnIndex == 1)
            {
                e.Value = m_data[e.RowIndex].Zeit;
            }
            else if (e.ColumnIndex == 2)
            {
                e.Value = m_data[e.RowIndex].Typ;
            }
            else if (e.ColumnIndex == 3)
            {
                e.Value = m_data[e.RowIndex].Telegramm;
            }
            else if (e.ColumnIndex == 4)
            {
                e.Value = m_data[e.RowIndex].Daten;
            }
        }


    public class StringObjekt
    {
        private string m_Zeile;
        private string m_Zeit;
        private string m_Typ;
        private string m_Telegramm;
        private string m_Daten;

        public string Zeile
        {
            get { return m_Zeile; }
            set { m_Zeile = value; }
        }
        public string Zeit
        {
            get { return m_Zeit; }
            set { m_Zeit = value; }
        }
        public string Typ
        {
            get { return m_Typ; }
            set { m_Typ = value; }
        }
        public string Telegramm
        {
            get { return m_Telegramm; }
            set { m_Telegramm = value; }
        }
        public string Daten
        {
            get { return m_Daten; }
            set { m_Daten = value; }
        }
    }

Leider stimmen jetzt aber durch die DataSource die Spaltenbreiten und Zeilenhöhen nicht mehr 😦
Und jede Spalte taucht jetzt zweimal auf dem DGV auf... (was man aber leicht durch das löschen der standartspalten im DGV beheben könnte, wodurch aber die Dimensionen der zellen verloren gehen würden (höhe, breite, zentrierter Tex etc.)
ist es nicht irgendwie möglich die einzelnen Spalten des "StringObjekt" an die Spalten des DGV zu binden, ohne viel eventabfangen und sowas???

[EDIT:]
Die folgende Zeile hat das Problem gelöst:

dataGridView1.AutoGenerateColumns = false;
14.06.2010 - 13:10 Uhr

Habe es schonmal ausprobiert, habe also ein paar Beispiele aus dem Internet angeschaut, kopiert und für meine Anwendung modifiziert... allerdings bin ich dann auf probleme gestoßen, die ich bis dato nicht lösen konnte...

D.h. ich müsste mich erst ein bisschen intensiver mit dem Vitruellen Modus beschäftigen, was ich heute auch getan habe, allerdings ist man quasi in jedem Beispiel von Bereits existierenden Daten ausgegangen.

Und da habe ich mir die Frage gestellt, ob ich meine Probleme mit dem Vituellen Modus deshalb nicht lösen konnte, weil er vielleicht garnicht für zur Laufzeit entstehende Daten gedacht ist?

Aber ok, ich werde jetzt mal versuchen das ganze zu implementieren...

Zurzeit schaut meine Lösung jedoch so aus:

Mein Datagridview besteht maximal aus 14 zeilen... wenn eine neu Zeile dazukommt, wird die erste rausgelöscht (FILO)...
habe jetzt schon knapp 400.000 zeilen eingelesen... ein Ende ist nicht in sicht
habe es auch mal probiert, dass mein DGV maximal aus 1000 Zeilen besteh aber da ist der Fehler immer noch aufgetreten 😦

14.06.2010 - 12:50 Uhr

Verständnisfrage:

Wenn ich viele Daten anzeigen will, dann benutze ich den Virtuellen Modus...

aber was ist, wenn die Daten erst zur Lauftzeit eingelesen werden? Bringt dann der Virtuelle Modus dann überhaupt noch etwas? Da ja so oder so jede einzelne Zeile ausgegeben wird?

09.06.2010 - 15:14 Uhr

😦@Th69: Das waren doch schon genug gute tipps^^ Besser Qualität als Quantität^^

Ich habe mich jetzt ein paar Tage mit meinem Problem rumgeschlagen... ohne Erfolg 🙁
Jedenfalls konnte ich das Hauptproblem nicht lösen, jedoch ein paar kleinere Fehlerquellen beseitigen, sodass das Programm stabil läuft.

Der Fehler: "TargetInvocationException wurde nicht behandelt." kam durch diesen Methodenaufruf zustande:

dataGridView1Paint(Convert.ToInt32(sRow[0]) - 1, Convert.ToChar(sRow[2].Substring(0, 1)));   // Zeilen colorieren

in meinem ersten Beitrag sah die Zeile allerdings noch anders aus, nämlich:

dataGridView1Paint(daten.zeile - 1, daten.typus);

Habe den Code ein wenig umgeschrieben. Die Ausnahme tritt nun nicht mehr auf.

Zitat von Th69:

Es könnte auch angebrachter sein, zuersteinmal einige Rows in einer Liste zu sammeln, ehe sie dann in einem Rutsch dem DGV hinzugefügt werden.

Hatte ich schonmal gemacht gehabt, was aber keinen Erfolg brachte. Da sich mein Code aber in der zwischenzeit etwas geändert hatte, speichere ich nun die Daten in einem Buffer zwischen und gebe dann 13 Zeilen auf eimal aus (Es sind immer nur 13 Zeilen sichtbar).
Ergebnis: Programm läuft nun bis ca. 40.000 Zeilen (also doppelt so viele Zeilen wie sonst).

        void ZeileAnzeigen(string[][] sRowBuffer)
        {
            if (dataGridView1.InvokeRequired)
            { // Wenn Invoke nötig ist, ...
                // dann rufen wir die Methode selbst per Invoke auf
                this.BeginInvoke(new ZeileAnzeigenDelegate(ZeileAnzeigen), new object[][] { sRowBuffer });
                return;
            }
            // eigentlicher Zugriff; läuft jetzt auf jeden Fall im GUI-Thread

            SuspendLayout();

            for (int m = 0; m < 13; m++)
            {
                dataGridView1.Rows.Add(sRowBuffer[m]);
                dataGridView1Paint(Rowcounter, sRowBuffer[m][2]);
                Rowcounter++;
            }

                dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;

            ResumeLayout();
}

Aja, außerdem speichere ich die Daten jetzt in eine Queue (Zwischenspeicher^^):

                        Queue wrapper = Queue.Synchronized(queuebuffer);
                        wrapper.Enqueue(workBuffer);

Und blockiere die beiden Threads (Einlese- und Ausgabethread) per AutoResetEvent, wodurch meine CPU-Auslastung von 100% auf ~8% gesunken ist(bei weniger als 1000 Zeilen) die aber auf ca. 40% steigt (bei ca. 80.000 Zeilen).

Und jetzt kommt ein absolut seltsames Verhalten, dass ich mir nicht erklären kann:

Ich empfange ein Datenpaket, dass aus mehreren Befehlen besteht (z.B. aus zwei Befehlen). Sobald die Daten in die Queue eingespeichert wurden, wird die Blockierung des zweiten Threads aufgehoben. Der zweite Thread (Ausgabethread) gibt dann die Daten asynchron aus, bis die Queue keine Elemente (Befehle) mehr besitzt und wartet dann, bis wieder ein Datenpaket reinkommt. Die Queue ist somit nie größer als 5 Elemente.
Nach ca. 40.000 Zeilen, werden aber Befehle verschluckt (Die Daten sind schon beim Einlesevorgang nicht mehr vorhanden) 🙁

Wenn ich jedoch nach jedem Datenpaket immer NUR EINEN Befehl ausgebe, also nur EIN ELEMENT von der Queue abhole, dann wächst meine Queue zwar an (da ja ein Datenpaket aus MEHREREN Befehlen besteht, ich aber immer nur EINEN Befehl ausgebe und danach warte bis ein neues Datenpaket ankommt), aber dafür werden keine Befehle mehr verschluckt!?
(Habe über 100.000 Zeilen ausgegeben, die Queue hatte da eine größe von ca. 70.000 Elemente d.h. ich gebe nur in etwa die hälfte der Befehle in der gleichen Zeit aus, dafür werden aber KEINE Befehle mehr verschluckt!?)

Also meiner Ansicht nach Blockiert die Ausgabe das Einlesen der Daten. Wahrscheinlich weil das DGV mit zunehmender Anzahl der Zeilen mehr Zeit oder RAM oder sonst was braucht 🙁

Hat vielleicht noch irgendjemand tipps für mich?^^

02.06.2010 - 14:29 Uhr

Hallo Th69,

danke für den Hinweis, aber die FAQ kenne ich bereits und habe leider nix gefunden, was mir jetzt noch weiterhelfen kann. Aber trotzdem danke für den Hinweis.

@all:
Also ich bin der Lösung meines Problemes schon auf den Fersen und glaube zu verstehen, wieso es zu diesen Ausnahmen kommt:

Ich bin bei meiner Suche auf diesen Thread gestoßen:

Backgroundworker + TargetInvocationException

Kann es sein, dass ich die Invokemethode zu oft aufrufe? Oder spielt das keine Rolle?

01.06.2010 - 15:22 Uhr

Danke für eure Tipps =)
Habe jetzt mal einen Einlese- und Ausgabethread gemacht.

Der Einlesethread schaut jetzt so aus:

public void MyProcedure2()
{
        while (true)
            {
                if (EtherNet.haveRx)
                {
                        EtherNet.haveRx = false;
                        queuebuffer.Enqueue(EtherNet.rxString);
                 }
             }
}

Beim Ausgabethread habe ich zusätzlich noch das eingefügt:

Thread.Sleep(20);

Außerdem habe ich "invoke" durch "Begininvoke" ersetzt, das dank des Queue keine Fehler mehr verursacht.

Ich komme mit meinem Programm jetzt schon auf über 50.000 Zeilen 😁
Und kann das Fenster jetzt auch öfter minimieren oder verschieben, ohne das Daten verloren gehen.
Allerdings ist der Fehler immer noch nicht ganz behoben 🙁

Ab und zu bekomme ich auch eine ganz andere (neue) Exception:

static class Program
    {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 form1 = new Form1();
            Application.Run(form1); //<- hier kommt der Fehler
        }

"TargetInvocationException wurde nicht behandelt."
"Ein Aufrufziel hat einen Ausnahmefehler verursacht"

oder manchmal auch dieser Fehler (Code wurde vom Designer automatisch erstellt):

        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

"InvalidOperationException"
"Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."

Manchmal tritt der erstgenannte Fehler zu erst auf, manchmal der zweite. Außerdem tritt er manchmal sofort (noch vor der Ausgabe des ersten Befehls) auf.
Wenn ich die zeile "Thread.Sleep(20)" im Ausgabethread weglösche, dann kommen diese Fehler immer und das noch vor der 150. Zeile X(

hat jemand vielleicht eine Ahnung woher die Fehler kommen? Und ob sie vielleicht was mit dem Datenschwund meines Programmes zu tun haben?

01.06.2010 - 08:54 Uhr

ok, vielen Dank 😁

jetzt weiß ich ja was ich machen muss... ich hatte da im Sinn einfach zwei Threads
laufen zu lassen, der eine liest Daten ein, der andere gibt Daten aus.

Soweit so gut, jetzt treten aber folgende Probleme auf:

1.)

Das Einlesen der Daten geschieht schneller, als das Ausgeben. D.h. ich kann
keinen Ringpuffer mehr zum Einspeichern benutzen und muss zwangsläufig ein Array benutzen, das ins unendliche wächst (Ich möchte ja so viele Befehle einlesen wie möglich) oder ich mache die Ausgabe schneller.
Kann man die Ausgabe über DatagridView irgendwie beschleunigen?
Anmerkung: Das würde natürlich nur bezwecken, dass das Array nicht ins unendliche wächst, aber nicht das SICHERE Einlesen der Daten 🙁 (Z.B. würden schon beim Minimieren des Fensters Daten verloren gehen)

Deshalb komme ich zu Problem Nr.:

2.)

Wie kann ich sicherstellen, dass der "Einlese-Thread" IMMER einlesen darf, und nicht durch das Ausgeben der Daten oder sogar durch das minimieren des Fensters behindert wird? Einfach die Priorität hochzusetzen hatte keinen Erfolg, da der "Einlese-Thread" einfach nur mehr Zeit zugeteilt bekommt, wodurch der "Ausgabe-Thread" noch weniger Zeit zum Ausgeben hat und dadurch der Fehler schon wesentlich früher auftaucht?

31.05.2010 - 15:16 Uhr

@herbivore: Vielen Dank für die schnelle Antwort 🙂

habe jetzt mal nach dem Beschreiben der Textdatei das hier eingegeben:

Tread.Sleep(20);

Ergebnis: Es treten sehr viele Fehler auf! Sogar bei 2ms treten noch Fehler auf!

Das wa ja mal ein genialer Vorschlag von dir^^

ok, jetzt weiß ich, das meine Methode zu viel zum Rechnen hat... bzw. dass das Zeichnen in DatagridView zu lange dauert (Aber: findet das nicht in einem anderen Thread statt oO? Sollte ja eigentlich unabhängig vom Einlesevorgang sein?)

Wie kann ich jetzt den Rechenaufwand der Methode verkürzen oder die Ausgabe von der Eingabe entkoppeln?

mfg Cuin

31.05.2010 - 14:05 Uhr

Hallo alle zusammen, ich habe hier ein Problem bei der Ausgabe von Daten mittels DatagridView.
Es geht um folgendes: Ich lese verschieden große Datenpakete per Ethernet aus, die dann verarbeitet und formatiert mittels DatagridView ausgegeben werden sollen. Bisher klappt alles ganz wunderbar... jedoch nur auf dem ersten Blick 🙁

Das DatagridView gibt zwar zunächst alle Daten wie gewünscht aus, doch ab ca. 20.000 Zeilen verschluckt das programm einige Datenpakete. D.h. bis ca. 20.000 Zeilen werden die Daten fehlerlos eingelesen und ab ca. 20.000 Zeilen tretet der Fehler mehr oder minder regelmäßig auf. Es wird immer maximal ein Datenpaket aufeinmal "verschluckt"! Also niemals mehr als zwei Datenpakete auf einmal.

Ich gehe folgendermaßen vor:

private void buttonPlay_Click(object sender, EventArgs e)
{
//Der Thread wird über einen Play-Button aktiviert
ThreadStart del = new ThreadStart(MyProcedure);
Thread myFirstThread = new Thread(del);
myFirstThread.Start();
}

Der Thread selber schaut so aus (Schematisch gesehen):

public void MyProcedure()
{
//Erstmal alle Variablen initiallisieren

//...
ASCIIEncoding enc = new ASCIIEncoding();
string ans = "";

int index1 = 0;
int index2 = 0;
//...
//usw.

//Dann kommt der große while-Block, der jetzt einfach mal ewig laufen soll

while (true)
{
                
/* Ringpuffer mit Daten füllen */
while (true)
{
 if (EtherNet.haveRx)    //wenn er was empfangen hat, dann Schleife verlassen
{
EtherNet.haveRx = false;
ans = EtherNet.rxString;

break;
}
}

arr = enc.GetBytes(ans);

//Dann werden die relevanten Daten aus dem "Buffer" gelesen... 

/* Da ein Datenpaket aus mehreren "Befehlen" besteht, wird jeder Befehl jeweils
in einen "workBuffer" gespeichert, verarbeitet und im DatagridView eingelsen, bis
kein oder kein kompletter Befehl mehr vorhanden ist */



for (solange noch nicht alle Bytes ausgelesen)
{
if(kompletter Befehl vorhanden)
{
//Bearbeite den Buffer und speicher die Daten in einen String-Array ein

sRow[0] = ZahltoString(daten.zeile);
sRow[1] = daten.timer;
//...
sRow[3] = enc.GetString(daten.telegramm);

//Jezt wirds spannend: Gebe die Daten aus:

ZeileAnzeigen(sRow);
}
}
}

Um die GUI aufzurufen gehe ich folgendermaßen vor: (An dieser Stelle vielen Dank für die ausführliche FAQ zum Thema invoke 👍)

        void ZeileAnzeigen(string[] sRow)
        {
            if (dataGridView1.InvokeRequired)
            { // Wenn Invoke nötig ist, ...
                // dann rufen wir die Methode selbst per Invoke auf
                dataGridView1.Invoke(new ZeileAnzeigenDelegate(ZeileAnzeigen), new object[] { sRow });
                return;
            }
            // eigentlicher Zugriff; läuft jetzt auf jeden Fall im GUI-Thread
            dataGridView1.Rows.Add(sRow);

            dataGridView1Paint(daten.zeile - 1, daten.typus);   // Zeilen colorieren

                dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;

        }

Folgende Dinge habe ich schon ausprobiert:

  • Anstatt die Daten in DatagridView auszugeben habe ich die Daten in eine Textfile gespeichert: nach 200.000(!) Zeilen ist immer noch kein Fehler aufgetaucht.
  • habe diese Zeile auskommentiert: "dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;" dadurch hat sich der Fehler von ca. 20.000 auf die ca. 28.000 Zeile verschoben. (d.h. der Fehler tritt wesentlich später auf)
  • ich habe versucht die Priorität des Threads auf "highest" hoch zu setzen -> der Fehler tritt immer noch auf
  • ich habe verschiedene Blöcke mit Monitor.Enter() und Monitor.Exit() vor fremden zugriff geschütz: kein erfolg
  • habe die Daten mit hyperterminal eingelesen: es tritt NIE ein fehler auf...

Vielleicht sollte ich noch erwähnen, dass der Fehler nicht immer an der gleichen stelle auftritt... manchmal kommt er schon nach 15.000 Zeilen, oder erst nach 24.000 Zeilen. Aber er kommt NIE vor 10.000 Zeilen....
Um 20.000 befehle auszugeben muss ich ca. 4 minuten warten.
VS zeigt mir auch keinen Fehler an, da die reihenfolge der eingelesenen Befehle immer die gleiche Struktur aufweist, kann ich fehlende Befehle trotzdem leicht erkennen.

Also ich hoffe, dass ihr mir weiter helfen könnt. Für Rückfragen stehe ich gerne zur Verfügung. Vielleicht sollte ich noch erwähnen, dass die mein erster Beitrag ist 😉

mfg Cuin