Button nicht Klickbar wenn die Class noch Arbeitet

  • C#

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Radinator.

    Button nicht Klickbar wenn die Class noch Arbeitet

    Moin die runde,
    ich habe da mal wieder ein spannendes Problem wo ich nicht weiter komme.

    Main ruft eine Class auf und macht dort für ein paar Minuten, viele dinge. Ich möchte aber das, wenn in der Main ein Button "STOP" gedrückt wird, dass Arbeiten in der Class beendet wird.
    Ich habe das auch alles so gebastelt das diese Grundsätzlich funktioniert, aber ich kann während des Arbeiten in der Class, nicht auf den Button drücken... :( kann ich den nicht drücken, wird auch nichts gestoppt. Jemand ne Idee?...
    Schau Dir mal Multithreading an.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Spannendes Thema!
    Hier gibt es ein excellenten Artikel darüber codeplanet.eu/tutorials/csharp…ithreading-in-csharp.html <- mehr geht nicht.

    Problem habe ich trotzdem noch ;)
    Der Thread läuft für die Class, aber ich habe dort auch ein Event welches Feuert. Das gefällt dem Thread ja so gar nicht da es nicht in dem selben Thread ist. Jemand ein Tipp für mich?

    C#-Quellcode

    1. using System.Threading;
    2. ...
    3. Thread Creator;
    4. ...
    5. Creator = new Thread(losgehtes);
    6. Creator.Start();
    7. ...
    8. private void losgehtes()
    9. {
    10. Class aufruf... (EVENT will Feuern...FEHLER!!!)
    11. }

    Mal ganz vereinfacht dargestellt, was ich gebastelt habe.

    Pardasus schrieb:

    Jemand ein Tipp für mich?
    Setze dich mit den Links auseinander, die man dir im Gespräch empfiehlt.
    Suche nicht end- und plan-los weiter nach sonst allen Artikeln die's gibt.

    Wozu soll ich dir was empfehlen, wenn du an meine Tipss gar nicht interessiert bist, und stattdessen iwas ganz annerem hinterherrennst?
    Als erste wurde nur ein Stichwort in raum geworfen und ich musste selbst weiter suchen im Internet:
    Schau Dir mal Multithreading an.


    Danach hast Du die nächsten Begriffe in Raum geworfen:
    Async, Await und Task


    Wo ich erst jetzt erkennen konnte, dass dies ein Link zu einem anderen Thread ist der allerdings auf VB.NET verweist. Ich bin aber in C# unterwegs.
    Ich bin noch recht neu dabei, aber eine Lösung konnte ich in dein Thread trotz VB.NET nicht erkennen.

    Links? Ich habe nur deinen gefunden, war da noch einer?!
    Grundsätzlich sei gesagt, dass VB.Net und C# beide auf dem .Net-Framework laufen und deshalb nahezu 1:1 konvertierbar sind.
    Beim Multithreading gibt es mehr oder weniger 3 Arten:
    • Backgroundworker(nicht so doll)
    • ein normaler Thread
    • Tasks bzw Async und Await
    Ob du jetzt mit Thread oder Task arbeitest würde ich erstmal an der Framework-Version festmachen, wenn du >4.5 benutzen willst würde ich Async/Await benutzen, da es übersichtlicher ist. Ansonsten halt ein Thread.
    Egal was du jetzt benutzt, deine Klasse sollte asynchron arbeiten, Events an die GUI werfen(sowas wie "hey ich bin fertig, deaktiviere den Button") und die GUI(also der Button) muss der Klasse mitteilen, dass sie jetzt stoppen soll.
    Letzteres kann man bspw ganz simpel über eine Flag, also Boolea-Property regeln.

    Bei Zweiterem muss man aufpasse, denn die GUI mag es garnicht wenn man in ihr von einem Nebenthread aus rumpfuscht(wäre ja auch dumm wenn ein Nebenthread bspw permanent irgendwelche Properties setzt und die GUI sich ständig neuzeichnen müsste). Lösung des Problems bedeutet Invoke. Also im Event der Klasse Invoke oder besser noch BeginInvoke aufrufen. Bei ersterem wird gewartet bis die GUI des ausführt, bei letzterem kann die GUI des später ausführen und der Thread kann einfach weitermachen.

    Und Ersteres sollte eigentlich klar sein: Per Thread oder Task(also Async/Await) die Klasse aufrufen, also die Methode aufrufen, die die Klasse arbeiten lässt.

    LG
    Wie bereits erwähnt musst du das benötigte Steuerelement invoken das machst du bei Threads mit einem MethodeInvoker. Kleines Beispiel hier wird in label1 ein Text ausgegeben wenn der Event gefeuert wird.

    Spoiler anzeigen

    C#-Quellcode

    1. EineKlass myClass;
    2. private void Form1_Load(object sender,...)
    3. {
    4. myClass = new EineKlasse();
    5. myClass.DerEvent += OnDerEvent;
    6. }
    7. private void OnDerEvent(object sender,...)
    8. {
    9. If (label1.InvokeRequired)
    10. label1.Invoke(new MethodeInvoker(delegate() {
    11. label1.Text = "OnDerEvent";
    12. }));
    13. else
    14. label1.Text = "OnDerEvent";
    15. }

    Pardasus schrieb:

    Als erste wurde nur ein Stichwort in raum geworfen und ich musste selbst weiter suchen im Internet:
    Schau Dir mal Multithreading an.
    Jo, so reingeworfene Stichworte bringen Anfängern wirklich nicht viel - "Anschauen" kann ja alles bedeuten, und hast du ja eiglich gut gemacht, und sieht man, dasses nix bringt.
    (Also dein Fundstück ist wirklich gut, wenn man Threading unter der Haube genau verstehen will - nur womit genau Problemlösung anfangen - das findet man in der Menge der Info nicht.


    Danach hast Du die nächsten Begriffe in Raum geworfen:
    Wo ich erst jetzt erkennen konnte, dass dies ein Link zu einem anderen Thread ist
    Dass man das nicht als Link erkennen könnte, daran habich nicht gedacht. Weil ist ein himmelweiter Unterschied, ob man Stichworte schmeisst, oder auf ein Tutorial verlinkt.

    Ich bin aber in C# unterwegs.
    Das tut in .Net-Fragen weniger zur Sache. Normal sollte man vb-code dann auch so leidlich verstehen, ansonsten gibts auch Online-Übersetzer, oder man fragt halt.
    Aber wie gesagt: Meist nichtmal nötig

    aber eine Lösung konnte ich in dein Thread trotz VB.NET nicht erkennen.
    Hast du die Samples denn mal laufen lassen, konntest du dich davon überzeugen, dass da Code im NebenThread läuft, der das Gui nicht blockiert?
    Und dasss man die Nebenläufigkeit auch canceln konnte?

    Aber ich hab auch viel besseres Tut, aber auf englisch:
    codeproject.com/Articles/10296…ithout-any-additional-Lin
    Der didaktische Aufbau ist anhand vb-Beispielen, aber die Samples sind auch c#.
    Da wird das komplette Programm entwickelt, weil Gui entblocken ist zunächstmal ein Kinderspiel, aber es hängen bis zu 4 weitere Folge-Probleme dran, die auch zu lösen sind - also insgesamt ein 5-fach-Problem:
    1. Unblocking
    2. Gui-Suspending
    3. Progress-Report
    4. Cancellation
    5. Error-Handling

    (Übrigens, wenn dir das Tut was gebracht hat, upraten - dasses häufiger gelesen wird)

    Links? Ich habe nur deinen gefunden, war da noch einer?!
    So - jetzt sind es mehrere.

    ;)

    Pardasus schrieb:

    ein Button "STOP" gedrückt wird, dass Arbeiten in der Class beendet wird
    Du erstellst einen eigenen Thread oder einen Task (kann auch generisch sein), übergibtst beim Erstellen ein CancellationToken und schickst ihn auf die Arbeit. Damit entblockst du schon mal das GUI. Wenn du nun den Button drückst, dann rufst du im Button_Click-Event this.cancellationToken.Cancel auf.

    Das Token muss natürlich global sein.

    Hier mal ein Code-Listing:
    "C#-Code"

    C#-Quellcode

    1. using System;
    2. using System.Threading;
    3. using System.Windows.Forms;
    4. using System.Threading.Tasks;
    5. namespace ThreadTest2
    6. {
    7. public partial class Form1 : Form
    8. {
    9. private DoSomething ds;
    10. private CancellationTokenSource cts;
    11. private Task tsk;
    12. public Form1()
    13. {
    14. InitializeComponent();
    15. this.ds = new DoSomething();
    16. this.cts = new CancellationTokenSource();
    17. this.tsk = new Task(this.ds.DoMuchWork, this.cts.Token);
    18. }
    19. private void btnStart_Click(object sender, EventArgs e)
    20. {
    21. this.tsk.Start();
    22. }
    23. private void btnStop_Click(object sender, EventArgs e)
    24. {
    25. if (!this.cts.IsCancellationRequested) {
    26. this.cts.Cancel();
    27. }
    28. }
    29. }
    30. public class DoSomething
    31. {
    32. public void DoMuchWork()
    33. {
    34. while (true)
    35. {
    36. Thread.Sleep(2000);
    37. }
    38. }
    39. }
    40. }


    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Radinator“ ()