Felix  RuthenbergAsynchrones Verarbeiten von WinFormEvents (Ein Beispiel)


Problemstellung:
Eine Textbox soll zyklisch alle 2 Sekunden mit der aktuellen Uhrzeit gefüllt werden.  Dieser Prozess soll als Worker Thread im Hintergrund laufen, damit andere Threads (zum Beispiel das UI) nicht weiter davon betroffen sind.  Außerdem soll es möglich sein über einen Button weitere Zeilen in die Textbox einzufügen ohne dabei Threadverletzungen zu Riskieren.

Lösungsansatz:
Während der Ausführung des Asynchronen Threads kann die Invoke Methode der Form aufgerufen werden, die eine kurze Anweisung aus dem Worker Prozess übernimmt und ausführt.  Diese kurze Anweisung besteht aus dem Setzen des neuen Textes und wird somit für das Control im Main Thread ausgeführt.  Mit Hilfe dieser Vorgehensweise lassen sich also langwierige Berechnungen auslagern und aus diesem asynchronen Teil heraus können Methoden, die den Main Thread benötigen (zum Beispiel weil auf Controls des Mail Threads zugegriffen werden soll) weiterhin auf diesem ausgeführt werden.

Das Beispiel:
Im Beispiel Projekt ist eine TextBox (txtbxResult), sowie drei Buttons (btnStart, btnStop und btnInterfere) instanziiert.  Außerdem gibt es auf Klassenebene eine Delegatdefinition (delegateWriteText), die eine Methodensignatur ohne Rückgabewert aber mit einem string Parameter definiert sowie ein boolscher Bezeichner asynchOn und ein Thread Bezeichner mit Namen t.

Starten des Asynchronen Threads:
Beim Erstellen des neuen Threads kann die auszuführende Funktion übergeben werden.  Außerdem wird das asynchOn Flag gesetzt um anzuzeigen, dass der asynchrone Prozess läuft.

private void btnStart_Click(object sender, EventArgs e)
{
  asynchOn = true;
  btnStart.Enabled = false;
  t = new Thread(WriteTextAsynch);
  t.Start();
}

Die asynchrone Methode:
In einer while Schleife wird das asynchOn Flag geprüft und so lange ausgeführt wie dieses auf true steht.  Dieses Verfahren hilft den asynchronen Thread durch simples Ändern des Flags zu beenden.  Die Eigenschaft InvokeRequired gibt an ob das Control von dem derzeitgen Prozess angesprochen werden kann oder nicht.  (In diesem Beispiel ist das nie der Fall, denn die Funktion wird nur vom asynchronen Thread aufgerufen, die Abfrage ist als hier redundant und nur zu Demozwecken angegeben.)  Die Instanziierung des Delegaten zeigt auf die Synchrone WriteTextSynch Methode und wird zusammen mit einem Parameter (der entsprechende String) in der Invoke Methode der Form Übergeben.  Die Invoke Methode sorgt dafür, dass die übergebene Delegat Methode im Main Thread ausgeführt wird.

private void WriteTextAsynch()
{
  delegateWriteText d = new delegateWriteText(WriteTextSynch);
  while (asynchOn)
  {
    if (txtbxResult.InvokeRequired)
    {
      this.Invoke(d, String.Format("Invoked Asynchronously at {0}{1}", DateTime.Now.ToLongTimeString(), Environment.NewLine));
    }
    Thread.Sleep(2000);
  }
}

Die synchrone Methode:
Fügt den übergebenen Text an den Text in txtbxResult an

private void WriteTextSynch(string text)
{
  txtbxResult.Text += text;
}

Der Interfere Button:
Hier kann die synchrone Methode einfach aufgerufen werden, denn auch die entsprechende ButtonClick Event Handler Methode wird im selben Thread ausgeführt, der auch den Button erstellt hat:

private void btnInterfere_Click(object sender, EventArgs e)
{
  WriteTextSynch(String.Format("Written Synchronously at {0}{1}", DateTime.Now.ToLongTimeString(), Environment.NewLine));
}

Der Stop Button:
Setzt das Flag auf false und veranlasst so die asynchrone Methode die Ausführung zu beenden.

private void btnStop_Click(object sender, EventArgs e)
{
  btnStart.Enabled = true;
  asynchOn = false;
}

Der Quellcode:
Das Beispiel kann heruntergeladen werden von:
http://cid-fd4d63530af59c99.skydrive.live.com/self.aspx/.Public/Asynch.zip



Kategorien: C#;.Net; 03.04.2009 12:59:49


 


Neuen Kommentar einfügen:

  Titel:   
  Name:
  E-Mail:
  Kommentar:

 
 


Kommentare




© Copyright 2008 ppedv AG