1. #1
    Avatar von Snees
    Registriert seit
    18.11.2011
    Beiträge
    1.001
    Thanked 590 Times in 319 Posts

    Standard Methode "im Hintergrund" ausführen

    Hallo, folgende Situation:

    Ich habe eine Windows-Form mit einem Button und einem Label,
    bei einem Klick auf den Button wird folgender Code ausgeführt:


    for (int i = 1; i <= 100; i++)
    {
    label1.Text = i.ToString();
    System.Threading.Thread.Sleep(100);
    }


    Mein Problem ist, dass sich die Form "aufhängt", während diese Schleife durchlaufen wird, man keinen anderen Button mehr klicken kann und ich nicht die Veränderung des Label-Textes sehen kann, sondern dort direkt 100 steht nachdem die Schleife durchlaufen wurde.

    Derartige Projekte habe ich bis jetzt immer mit einer Konsolenanwendung realisiert, weil dort die Ausgabe so aussehen würde:
    1
    2
    3
    4
    5
    6
    7
    Gibt es eine Möglichkeit diese Methode "im Hintergrund" auszuführen, sodass auch andere Buttons weiterhin anklickbar sind und ich auch alle 100ms eine Veränderung des Label-Textes sehe?

    Ich hoffe ich habe mich verständlich ausgedrückt.

  2. #2

    Registriert seit
    19.11.2011
    Beiträge
    496
    Thanked 412 Times in 268 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Dein GUI hängt sich auf, weil du alles in einem Thread ausführen lässt.
    GUI-Kram kommt in einen Thread, Logik in einen anderen.

    Schau mal hier:
    Threading (C#)

  3. The Following User Says Thank You to Mr. White For This Useful Post:

    Snees (07.03.2013)

  4. #3
    Avatar von Snees
    Registriert seit
    18.11.2011
    Beiträge
    1.001
    Thanked 590 Times in 319 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Okay, danke.

    Wenn ich die Methode in einem neuen Thread starte bekomme ich folgenden Fehler:
    Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement label1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
    Habe es mal mit Invoke versucht, weiß aber nicht, ob ich es richtig eingesetzt habe.


    using System;
    using System.Windows.Forms;
    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
    System.Threading.Thread newThread;
    newThread = new System.Threading.Thread(this.dothatshit);
    newThread.Start();
    MethodInvoker updateCounterDelegate = new MethodInvoker(dothatshit);
    Invoke(updateCounterDelegate);
    }
    private void dothatshit()
    {
    for (int i = 1; i <= 100; i++)
    {
    label1.Text = i.ToString();
    System.Threading.Thread.Sleep(100);
    }
    }
    }
    }



    Wenn ich das Programm so ausführe habe ich das gleiche Problem wie eben, GUI hängt sich auf und springt auf 100 und dann bekomme ich noch die oben genannte Fehlermeldung...

  5. #4

    Registriert seit
    19.11.2011
    Beiträge
    496
    Thanked 412 Times in 268 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Ob du es richtig eingesetzt hast, weiß ich nicht. Ich habe nur soviel Ahnung von C# wie es die Ähnlichkeit zu Java zulässt. ^^
    Aber habe dir mal was herausgesucht: [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke) | FAQ | myCSharp.de - DIE C# und .NET Community

  6. The Following User Says Thank You to Mr. White For This Useful Post:

    Snees (07.03.2013)

  7. #5
    Avatar von Snees
    Registriert seit
    18.11.2011
    Beiträge
    1.001
    Thanked 590 Times in 319 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Das hat mir geholfen, hier meine Lösung:


    using System;
    using System.Windows.Forms;
    namespace WindowsFormsApplication1
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
    System.Threading.Thread newThread;
    newThread = new System.Threading.Thread(this.dothatshit);
    newThread.Start();
    }
    private void dothatshit()
    {
    for (int i = 1; i <= 100; i++)
    {
    label1.Invoke(new MethodInvoker(updateLabel));
    updateLabel();
    System.Threading.Thread.Sleep(100);
    }
    }
    private void updateLabel()
    {
    Random random = new Random();
    int randomNumber = random.Next(0, 3);
    if (randomNumber == 0)
    {
    label1.Text = "0";
    }
    else if (randomNumber == 1)
    {
    label1.Text = "1";
    }
    else if (randomNumber == 2)
    {
    label1.Text = "2";
    }
    else if (randomNumber == 3)
    {
    label1.Text = "3";
    }
    else
    {
    label1.Text = "4";
    }
    }
    }
    }

  8. #6
    Avatar von uncopyable
    Registriert seit
    19.11.2011
    Beiträge
    282
    Thanked 235 Times in 120 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Dafür könntest du auch ein BackgroundWorker nutzen.

  9. The Following User Says Thank You to uncopyable For This Useful Post:

    Snees (07.03.2013)

  10. #7
    Gelöschter Benutzer
    Gast

    Standard AW: Methode "im Hintergrund" ausführen

    Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement label1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
    Kannste mit nem einfachem

    Code:
    CheckForIllegalCrossThreadCalls = false;
    in Form1() fixxen. Oder du invokest das Ganze:

    Code:
    Form1.Invoke((MethodInvoker)delegate {
    //..
    });
    Aber bitte nicht sowas umständliches was du da oben hast ^_^

  11. #8
    Avatar von DMW007
    Registriert seit
    15.11.2011
    Beiträge
    6.217
    Thanked 9.133 Times in 3.007 Posts
    Blog Entries
    5

    Standard AW: Methode "im Hintergrund" ausführen

    Zitat Zitat von Finn Beitrag anzeigen
    Kannste mit nem einfachem

    Code:
    CheckForIllegalCrossThreadCalls = false;
    in Form1() fixxen. Oder du invokest das Ganze:
    Da wird überhaupt nix gefixxt, sondern nur die Exception unterdrückt, die einen vor den Risiken warnen soll.
    Sobald du bei komplexeren Programmen mal ein paar Threads mehr hast wirds lustig, da können dann Deadlocks und andere witzigen Sachen auftreten die alle beteiligten Threads abschießen.
    CheckForIllegalCrossThreadCall ist dafür gedacht, die Prüfung abzustellen um die Performance zu erhöhen wenn definitiv sicher ist, dass keine Threadübergreifenden Vorgänge stattfinden können. Invoken ist performancemäßig logischerweise IMMER schlechter, da die betreffenden Threads sich vorher synchronisieren müssen um eben zb Deadlocks zu vermeiden.

    Wenn das Programm bei den hier geposteten 5 Zeilen bleibt ist das ganze natürlich noch nicht relevant und man könnte ohne große Probleme die Prüfung einfach abschalten. Aber sowas nem Anfänger zu empfehlen halte ich für äußerst fahrlässig, da kommt schnell der falsche Schluss bei raus dass zb Invoken vollkommen unnötig ist und man ja mit einer Zeile Code alle threadübergreifendenden Probleme 'beheben' kann. Wenn man halbwegs weiß wie Threads ablaufen und was man mit CheckForIllegalCrossThreadCalls genau bewirkt ist das was anderes, dann kann mans natürlich einsetzen. Wobei ich so an Murkserei grenzende Sachen prinzipiell nicht nutzen würde, außer es geht wirklich um Performance (da nutzt man dann tendenziell aber auch eher andere Sprachen wie C++ oder Asm).
    Fehler zu unterdrücken ist generell keine besonders gute Idee.


  12. The Following 3 Users Say Thank You to DMW007 For This Useful Post:

    Grammatikfehler (08.03.2013), Sky.NET (07.03.2013), ThunderStorm (08.03.2013)

  13. #9
    Avatar von Grammatikfehler
    Registriert seit
    24.04.2012
    Beiträge
    182
    Thanked 151 Times in 80 Posts

    Standard AW: Methode "im Hintergrund" ausführen

    Um alles mal in einem Button zu haben, kann man natürlich machen wie man will.

    Code:
            private void button1_Click(object sender, EventArgs e)
            {
                new Thread(delegate()
                {
                    for (int i = 1; i <= 100; i++)
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            label1.Text = i.ToString();
                        });
                        Thread.Sleep(100);
                    }
                }).Start();
            }

  14. The Following 2 Users Say Thank You to Grammatikfehler For This Useful Post:

    Sky.NET (08.03.2013), Snees (10.03.2013)

Ähnliche Themen

  1. Antworten: 3
    Letzter Beitrag: 11.02.2014, 09:32
  2. Antworten: 1
    Letzter Beitrag: 29.12.2013, 14:31
  3. Antworten: 2
    Letzter Beitrag: 29.09.2012, 15:24
  4. Hacker-Angriff auf "World of WarCraft" und "Diablo 3"!
    Von Waterpolo im Forum Gaming-News
    Antworten: 3
    Letzter Beitrag: 10.08.2012, 23:35
Diese Seite nutzt Cookies, um das Nutzererlebnis zu verbessern. Klicken Sie hier, um das Cookie-Tracking zu deaktivieren.