Laden...

Button soll trotz Ausführen aktiv bleiben

Erstellt von apollo vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.295 Views
A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren
Button soll trotz Ausführen aktiv bleiben

Hallo zusammen,

hoffe ihr könnt meine Frage hier beantworten, hab schon im forum gesucht aber brachte nichts.

Also mein Problem ist folgendes, bei einem Klick auf einen Button startet mein Modul eine Datenbankabfrage. Bei kurzen Tabellen ist das ja kein Problem, dauert ja nicht lange, aber wenn die Tabelle sehr lang ist dauert das schon ne Weile. Wenn mich aber nur die ersten Reihen interessieren, macht es ja sinn die Abfrage abzubrechen, wie in SQLTalk.

Jetzt wird aber das ganze Fenster während meiner Abfrage gesperrt. Genau das mächte ich unterbinden, sodass mein Button "Abbrechen" aktiv bleibt und ich die Abfrage auch stoppen kann. Wie kann ich den Button aktiv lassen?

Vielen Dank,

gruß apollo

2.223 Beiträge seit 2005
vor 17 Jahren

moin

längere Aktionen solltest du in einem Thread ausführen

und dazu findest du genug hier im Forum

mfg

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

supi 😁

gibt es nicht ein einfachen befehl, direkt den button freizugeben wie:


private void ausführen_Click(object sender, EventArgs e)
{
     gib den anderen button frei;
     mach den rest;
}

??

2.223 Beiträge seit 2005
vor 17 Jahren

das Problem ist, daß dein Button nicht gesperrt ist sondern einfach nicht auf irgendwelche Aktionen reagiert weil dein Programm in der Verarbeitung festhängt

mfg

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

hab grade mal nen bisl gegoogelt und hier im forum gesucht, aber leider nichts passendes gefunden. so schwer kann es ja eigentlich nicht sein oder? ich werd ma weiter suchen, freue mich aber trotzdem über hilfreiche antworten!

gruß apollo

2.223 Beiträge seit 2005
vor 17 Jahren
A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

ich arbeite seit wochen an dem modul, es wäre zu viel arbeit das jetzt nochmal zu ändern, alleine der code unter meinem butto_click ist mehrere Seiten lang, das ist es mir dann doch nit wert.
es gibt bestimmt einfachere methoden.

danke trotzdem

6.862 Beiträge seit 2003
vor 17 Jahren

Mehrere Seiten? Des ist ja mehr als nen schlechtes Design...

Ne einfachere Möglichkeit, naja Backgroundworker benutzen als Threadvereinfachung oder mal mit Application.DoEvents probieren, wobei das eher Behebung von Symptomen wäre statt die Ursache zu ändern.

Und soviel Arbeit ist des mitm Threading ja auch nicht. Im besten Fall ists ja einfach den Code im Button Click in ne eigene Funktion auslagern und diese Funktion dann in nem neuen Thread in deiner ButtonClick ausführen. Des wären insgesamt vielleicht 5 Zeilen mehr.

Baka wa shinanakya naoranai.

Mein XING Profil.

2.223 Beiträge seit 2005
vor 17 Jahren

Original von apollo
alleine der code unter meinem butto_click ist mehrere Seiten lang,

wenn das mal nicht früher oder später probleme macht

In einm Programm eine threadverarbeitung einzubauen sollte nicht so schwierig sein

solange mann nicht wirklich gravierende Design Fehler in seinem Code hat

mfg

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

Original von talla
Mehrere Seiten? Des ist ja mehr als nen schlechtes Design...

warum das denn? weiß ja nit was du beruflich machst, aber als anwendungsentwickler ist das halt standart, wenn nicht sogar wenig. muss halt auf einen button viel geprüft werden, hier nur einige beispiele:

-welche befehle stehen in der textbox (SQL, select (* oder nicht, mit oder ohne where, wie viele tabellen, mit aggregatfunktionien usw.), connect (wodran))
-welche datenbankconnection besteht (SQL, Oracle usw.)
-gewünschte änderungen in der maske setzen, die auf den buttonklick und den damit verbundenen ereignissen passieren
-die erhaltenen werte aus der datenbank manuell in ein datagrid füllen
-progressbar in bestimmter weise laufen lassen

und und und

klar, man könnte zig funktionen dafür bauen, aber da fehlt auch irgendwie der sinn bei...

also sag nochma was von wegen schlechtes design ^^

2.223 Beiträge seit 2005
vor 17 Jahren

Original von apollo

-welche befehle stehen in der textbox (SQL, select (* oder nicht, mit oder ohne where, wie viele tabellen, mit aggregatfunktionien usw.), connect (wodran))
-welche datenbankconnection besteht (SQL, Oracle usw.)
-gewünschte änderungen in der maske setzen, die auf den buttonklick und den damit verbundenen ereignissen passieren
-die erhaltenen werte aus der datenbank manuell in ein datagrid füllen
-progressbar in bestimmter weise laufen lassen

also sag nochma was von wegen schlechtes design ^^

Als Anwendungsentwickler ist genau sowas nicht Standart ich schließe mich talla an

mfg

6.862 Beiträge seit 2003
vor 17 Jahren

Grad bin ich wieder Student hab aber auch schon automotive Software geschrieben die auch schon im Einsatz ist 😉 Von daher weiß ich auch wie Software im professionellen Umfeld geschrieben wird.

klar, man könnte zig funktionen dafür bauen, aber da fehlt auch irgendwie der sinn bei...

Nee, des ist schon sinnvoll. So eine Funktion wie du sie hast über zig Seiten ist unwartbar. Ein Fehler irgendwo und man ist ewig in der Funktion am rumsuchen wo nun was schiefgeht. Auch haben die einzelnen Funktionsteile doch gar nichts mehr miteinander zu tun. Das sind für sich abgeschlossene Aktionen und die sollten auch in einzelne Funktionen ausgelagert werden. Oder was passiert wenn man mal auf die Idee kommt die GUI zu ändern bei euch? Oder sagen wir mal die Prüfung was nun in der TextBox steht wird an anderer Stelle noch gebraucht. Dann geht das große Refactoring bei euch los 😉

Aber des ist eh Offtopic, lassen wir des lieber.

Aber die Aktionen die du aufgezählt hast lassen jedenfalls darauf schließen das de rUmbau zum Threading bei euch nicht so leicht wäre da du die GUI in der Funktion veränderst und das müsste dann über Control.Invoke gehen usw. und dazu wäre doch mehr Code erforderlich. Aber hey, noch nen Grund das auszulagern. Datenbankarbeit könnte man ohne Probleme in nem Thread auslagern, wenn da nicht das zwischenwurschteln mit der GUI drin wäre die mit Datenbanken ja nichts zu tun hat 😉

Baka wa shinanakya naoranai.

Mein XING Profil.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

also es gibt keine kurze möglichkeit den button / mehrere controls aktiv werden zu lassen?

6.862 Beiträge seit 2003
vor 17 Jahren

Meines Erachtens nein.

Das ist einfach prinzipbedingt so. Wenn du blockierende Aktionen ausführst, dann kannst du in der Zwischenzeit nichts machen. Kannst versuchen Application.DoEvents() zwischendurch aufzurufen, damit gibst du dann kurzfristig die Chance einmal die Windows Messages abzuarbeiten. Aber des wird bei langandauernden Funktionen trotzdem nict verhindern dass die GUI einfriert.

Baka wa shinanakya naoranai.

Mein XING Profil.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

okay danke!

habs jetzt mal mit den threads versucht.

using System.Threading

eingefügt.
Jetzt möchte ich alles, was ich beim Klicken meines Buttons mache, mit diesem Thread ausführen.

so immerhin startet der den thread jetzt wenn ich auf den button klicke, aber ständig meckert mehr was von wegen "ungültiger threadübergreifender vorgang" an.
was nun? ^^

edit:

ich rufe auch nen paar funktionen innerhalb meines threads auf. muss ich die auch als thread darstellen?

6.862 Beiträge seit 2003
vor 17 Jahren

Ich zitier mich mal selber:

Aber die Aktionen die du aufgezählt hast lassen jedenfalls darauf schließen das der Umbau zum Threading bei euch nicht so leicht wäre da du die GUI in der Funktion veränderst und das müsste dann über Control.Invoke gehen usw. und dazu wäre doch mehr Code erforderlich

Schau einfach mal hier: [FAQ] Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel)

Einzelne Funktionen musst du nicht mehr extra als Thread starten, da die dann weiterhin im grad erstellten Thread laufen und somit immer noch parallel zur GUI.
Das Problem dass du in den Funktionen gesondert auf die GUI zugreifen musst bleibt aber natürlich weiterhin bestehen.

Baka wa shinanakya naoranai.

Mein XING Profil.

B
342 Beiträge seit 2006
vor 17 Jahren

Hi,
du kannst von einem Thread aus nicht auf ein Steuerelement zugreifen.
Stattdessen benutzt du Invoke.
Hier ein Beispiel zum Hinzufügen von Text zu einer Textbox:


public delegate void Add(string Text);

public void AddTextbox1Text(string Text)
{
     if(this.Textbox1.InvokeRequired)
           this.Textbox1.Invoke(new Add(this.AddTextbox1Text), new objec[]{Text});
     else
            this.Textbox1.Text += Text;
 }

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

ich lasse es lieber. wenn ich alle funktionen, die ich innerhalb des klicks aufrufen müsste, delegieren muss, jedes control mit invoke, nen neuen delegat und den ganzen kram hätte ich ja nen code der aneinandergeklebt so lang wie der eifelturm wär ^^

aber ich hab was gelernt:

immer schön threads benutzen und alles in funktionen auslagern ^^

bis dann und danke an alle

greetz apollo

6.862 Beiträge seit 2003
vor 17 Jahren

Du musst nicht alle Funktionen delegieren, nur die die auf irgendwelche GUI Controls zugreifen 😁

Aber freut mich das du doch noch erkennst das auslagern von Funktionen manchmal wohl nicht schlecht ist 😉

Baka wa shinanakya naoranai.

Mein XING Profil.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

ich will das aber schaffen man 😁

also das sind die controls auf die ich mit dem button zugreife:

eine datagrid, eine textbox, eine combobox, 2 radiobuttons, eine statusleiste mit mehreren Label, einer ProgressBar in der Statusleiste.

von diesen controls muss ich jetzt delegate erstellen oder wie?

oder von den funktionen? muss ich für jede funktion einen thread erstellen?

und mit dem invoke spreche ich die controls an die nicht im thread selber sind?

boah ist das kompliziert 😜 ich glaube ich geh mir mal nen kaffee holen ^^

6.862 Beiträge seit 2003
vor 17 Jahren

Ist gar nicht sooo kompliziert, Prinzip ist ja immer das gleiche - bissle Schreibarbeit isses, das stimmt 🙂

Also, du hast deine riesige ButtonClick Funktion. Die möchtest du in nem Thread auslagern um zu verhindern das die GUI einfriert bei langandauernden Funktionen.

Also lagerst du diesen Code erstmal in einen Thread aus. Alle Funktionen die du jetzt innerhalb dieses Threads aufrufst laufen auch in diesem Thread - sprich du brauchst nur diesen einen und alle Funktionen die du innerhalb aufrufst laufen auch da drin.

Jetzt kommt der nächste Schritt. Wenn du auf GUI Controls zugreifst, musst du nach dem Muster von Big Al's Code vorgehen. Bei dem Beispiel würdest du halt statt den Text direkt zu setzten, die Funktion AddTextBoxText aufrufen. Nach dem geposteten Muster ists dann auch egal ob du in dem GUI Thread bist oder in nem extra Thread - dafür ist die Abfrage mit dem InvokeRequired drin.

Und jetzt der blöde Teil - das musst du für jede Aktion machen die auf die GUI zugreift 🙂 Bei ner Textbox wie hier ists recht einfacht. Bei ner umfangreichen Funktion hast du als Beispiel den von mir geposteten Links wo ne TreeView gefüllt wird.

Hoffe jetzt ists bissle klarer. Dann mal viel Spaß 🙂

Baka wa shinanakya naoranai.

Mein XING Profil.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

okay mal für alle 😁

ich bin das ganz einfach umgangen.

einfach beim start der applikation nach InitializeComponent();

folgende Zeile einfügen:

Control.CheckForIllegalCrossThreadCalls = false;

dann klappt alles, und alles wunderbar, jeder ist glücklich, vor allem ich ^^

danke trotzdem an alle 🙂

greetz apollo

edit: eine frage hätte ich noch. wie breche ich den thread ab, wenn ich auf einen anderen button klicke. in der button_klick funktion habe ich den thread nicht zur verfügung...

edit 2:

hat sich erledigt, hab vergessen den thread global zu setzen ^^

danke und gruß

6.862 Beiträge seit 2003
vor 17 Jahren

Eigentlich fällt mir dazu jetzt nichts ein was nicht in so etwas wie nen argh enden würde =)

Die Exceptions hat man nicht eingebaut um User zu ärgern 🙂

Baka wa shinanakya naoranai.

Mein XING Profil.

187 Beiträge seit 2005
vor 17 Jahren

So kompliziert ist das nicht. Das Problem mit dem neuen Thread liegt daran, dass die Steuerelemente nicht zu dem aktuellen Thread gehören. Wenn ich Hintergrundarbeiten machen muss, die via Multithreading laufen sollen. erstelle ich mir meist ein neues Formular, welches ich mit Show aufrufe. Damit ist das Formular ein eigener Thread und enthält Steuerelemente, auf die es sofort zugreifen darf ohne den Umweg mit Invoke und delegaten.

Wenn du die Möglichkeit hast, das in andere Formulare zu verschieben, empfehle ich dir diese Möglichkeit, bevor du alles in neuen Thread umschmeisst. Dieses Thema ist knusprig und du solltest lieber damit etwas üben, bevor du größere Sachen damit startest.

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

okay 🙂

hab den thread wieder rausgeschmissen und dafür den backgroundworker genommen. funktioniert wunderbar, und den kann ich auch abbrechen wann ich möchte, ohne dass der vllt dann in einer schleife festhängt und die erst zuende bearbeitet.

so das wars dann erstmal, trotzdem danke.

bei meinem nächsten projekt werde ich mal von grund auf die threads benutzen, mal sehen obs dann auch einfacher klappt.

gruß apollo

A
apollo Themenstarter:in
72 Beiträge seit 2006
vor 17 Jahren

hallo nochmal 😁

dachte mir mal ich roll das wieder auf hier ^^

kleine zwischeninfo, hab doch den thread genommen, sieht irgendwie besser aus ^^

jetzt habe ich nur leider wieder nen problem, und die foren suche ergab auch nichts.

wenn der thread fertig ist, werden auch alle daten im datagrid korrekt angezeigt. funktionen vom datagrid sind auch alle okay, also anordnen nach name usw...

eine funktion aber fehlt leider: die scrollbars 😁

die werden teilweise angezeigt, funktionieren aber nicht. refresh bringt nichts, und die teile dynamisch zur laufzeit zu setzen bringt auch nichts.

ich weiss nicht mehr weiter !!! X( ?(

hat jemand ne idee?

187 Beiträge seit 2005
vor 17 Jahren

ich weiss nicht, ob ich dazu wirklich noch was schreiben soll...

du hast mit allen steuerelementen ein problem, wenn die nicht sofort zur verfügung stehen. ein update ist nicht effektiv.

ein neuer Thread, der die Steuerelemente mit Invoke aktualisiert ist das effektivste, was mir gerade einfällt.