Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Ausführung ans GUI delegieren per async+await oder per Thread+Control.Invoke

Moderationshinweis von herbivore (12.10.2013 - 19:22)

Abgeteilt von async/await: Verständnisfrage zur Ausführung in synchronen Methoden

uNki
myCSharp.de - Member



Dabei seit:
Beiträge: 58

Themenstarter:

beantworten | zitieren | melden

hi!

da meine frage thematisch ganz gut in diesen thread passt, mache ich keinen neuen auf.

ich habe ein label in der statusleiste meiner applikation. dies zeigt einfach nur die uhrzeit an und wird sekündlich aktualisiert. normalerweise würde ich einfach einen timer nehmen, interval auf 1000ms setzen und das label entsprechend aktualisieren.

ich möchte aber "am ball bleiben" und versuche es daher mal mit async/await.

im konstruktor der form rufe ich diese methode auf:


private async void RefreshDateTimeLabel()
        {            
            while (true)
            {
                await Task.Delay(1000);
                lblDateTime.Caption = String.Format("{0} {1}", DateTime.Now.Date.ToLongDateString(), DateTime.Now.ToLongTimeString());
            }
        }

zum verständnis: ich könnte das auch mit einem thread machen, hat das dann den gleichen effekt/technischen hintergrund wie die async/await methode oben?


private void RefreshDateTime()
        {
            Thread thread = new Thread(delegate()
            {
                while (true)
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new MethodInvoker(delegate()
                        {
                            Task.Delay(1000);
                            lblDatumUhrzeit.Caption = String.Format("{0} {1}", DateTime.Now.Date.ToLongDateString(), DateTime.Now.ToLongTimeString());
                        }));
                    }
                }
            });
            thread.Start();
        }

wenn ja, ist das async/await procedere ja wesentlich bequemer und lesbarer :)

danke und beste grüße!
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von uNki am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo uNki,

die Thread-Variante sollte man sinnvollerweise verändern/verkürzen zu (evtl. mit Control.BeginInvoke statt Control.Invoke):

private void RefreshDateTime()
{
    new Thread(() =>  {
        while (true) {
            Thread.Sleep(1000);
            this.Invoke((Action)(() => {
                lblDatumUhrzeit.Caption = String.Format("{0} {1}", DateTime.Now.Date.ToLongDateString(), DateTime.Now.ToLongTimeString());
            }));
        }
    }).Start ();
}

Erst damit hast du den gerechten Vergleich zu:


private async void RefreshDateTimeLabel()
        {            
            while (true) {
                await Task.Delay(1000);
                lblDateTime.Caption = String.Format("{0} {1}", DateTime.Now.Date.ToLongDateString(), DateTime.Now.ToLongTimeString());
            }
        }

Welche der beiden Varianten dann lesbarer ist, ist Geschmackssache. Die async-await-Variante ist etwas kürzer, dafür passiert alles implizit (und etwas magisch). Bei der Thread-Variante passiert das wechselseitige Delegieren zwischen den Threads explizit und damit möglicherweise leichter nachvollziehbar. Aber das ist wie gesagt Ansichtssache.

Wie du allerdings richtig sagst, würde man regelmäßige Aktionen im GUI-Thread sowieso am sinnvollsten mit System.Windows.Forms.Timer ausführen.

BTW: Man sollte DateTime.Now nicht zweimal aufrufen, weil sonst um Mitternacht die Zeit möglicherweise nicht zum Datum passt, sondern sich DateTime.Now einmal in einer Variable merken und diese zweimal verwenden.

herbivore
private Nachricht | Beiträge des Benutzers
uNki
myCSharp.de - Member



Dabei seit:
Beiträge: 58

Themenstarter:

beantworten | zitieren | melden

hallo herbivore,

danke für die erläuterungen und den tipp mit dem datetime.now!

du sagst, es wäre am sinnvollsten das mit einem system.windows.forms.timer zu realisieren.

gibt es hier auch eine begründung?

danke und beste grüße!
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.571

beantworten | zitieren | melden

Hallo uNki,

regelmäßige Aktionen, deren Hauptaufwand in der Aktualisierung der GUI liegen, sind eindeutig besser mit einem Timer auszuführen, da diese ja schon selbst im GUI-Thread ablaufen (und daher kein eigener Thread sowie GUI-Synchronisierung notwendig ist).
Nur wenn Berechnungen länger als 50-100ms brauchen (je Tick) oder aber in nicht vorhersehbaren Zeitabschnitten aktualisiert werden müssen, so sind Threads (bzw. Tasks) besser, s.a. [FAQ] Warum blockiert mein GUI?
private Nachricht | Beiträge des Benutzers
uNki
myCSharp.de - Member



Dabei seit:
Beiträge: 58

Themenstarter:

beantworten | zitieren | melden

danke!
private Nachricht | Beiträge des Benutzers