www.rolandk.de
- Aktuelle Themen zu .Net -
Achtung: Hier handelt es sich um meine alte Seite.
Die aktuelle ist unter folgendem Link erreichbar: www.rolandk.de/wp/
Home Blog Methoden im Gui-Thread verzögert ausführen




















































Methoden im Gui-Thread verzögert ausführen
Dienstag, den 07. Februar 2012 um 22:03 Uhr

Es klingt nach einen einfachen Problem: Man möchte nach einem bestimmten Ereignis in der Gui ein paar Hundert Millisekunden warten, bis schließlich eine Funktion angetriggert werden soll. Diese Situation ist denkbar, wenn man etwa möchte, dass in Windows.Forms zunächst die Oberfläche nach ein paar Klicks aktualisiert wird und erst dann eine weitere Logik ausgeführt wird. Wie würde man das lösen? Mit einem Timer, mit einem BackgroundWorker oder einen Thread? Klingt nach viel Overhead für ein einfaches Problem.

 

Nachdem ich in den letzten Wochen relativ viel mit dem ReactiveFramework gearbeitet habe und da vor allem die Throttle-Methode lieb gewonnen habe, dachte ich mir, ich möchte für dieses Problem eine ähnliche einfache Methode haben. Also eine Methode, sagen wir InvokeDelayed, der über ein Lambda eine Funktion übergeben wird und über eine TimeSpan Struktur der Zeitraum, der bis zur Ausführung gewartet werden soll. Am Ende ist nachfolgendes Coding dabei raus gekommen.

  1. /// <summary>
  2. /// Executes the given action after the given amount of time.
  3. /// </summary>
  4. /// <param name="action">The action to execute.</param>
  5. /// <param name="delayTime">The delay time.</param>
  6. public static void InvokeDelayed(this Control control, Action action, TimeSpan delayTime)
  7. {
  8. SynchronizationContext syncContext = SynchronizationContext.Current;
  9. if (syncContext == null)
  10. {
  11. throw new InvalidOperationException("No SynchronizationContext is available on current thread!");
  12. }
  13. if (syncContext.GetType() == typeof(SynchronizationContext))
  14. {
  15. throw new InvalidOperationException(
  16. "This method is not available on default synchronization context!");
  17. }
  18.  
  19. ThreadPool.QueueUserWorkItem(new WaitCallback((arg) =>
  20. {
  21. //Wait delay time
  22. Thread.Sleep((int)delayTime.TotalMilliseconds);
  23.  
  24. //Check if the control is still available
  25. if (control.IsHandleCreated)
  26. {
  27. syncContext.Send(new SendOrPostCallback((innerArg) =>
  28. {
  29. //Handle exception by global exception handler
  30. try { action(); }
  31. catch (Exception ex)
  32. {
  33. Application.OnThreadException(ex);
  34. }
  35. }), null);
  36. }
  37. }));
  38. }

Diese Methode ist als Erweiterungsmethode für die Klasse Control implementiert, kann also für jedes Control-Objekt direkt ausgeführt werden. Im Hintergrund wird über den ThreadPool ein Thread beauftragt, die übergebene Zeitspanne zu warten und dann den Gui-Thread mit dem übergebenen Lambda aufzurufen. Sieht etwas kompliziert aus, aber der Aufruf der Methode gestaltet sich relativ einfach, wie im folgenden Beispiel zu sehen.

  1. myForm.InvokeDelayed(
  2. () => DoSomethingOnGui(),
  3. TimeSpan.FromMilliseconds(500));

 

 

Kommentar hinzufügen

Ihr Name:
Kommentar: