Laden...

DelayedCall-Klasse: Funktionen asynchron zu einem späteren Zeitpunkt aufrufen

Erstellt von LonelyPixel vor 17 Jahren Letzter Beitrag vor 16 Jahren 4.636 Views
L
LonelyPixel Themenstarter:in
333 Beiträge seit 2007
vor 17 Jahren
DelayedCall-Klasse: Funktionen asynchron zu einem späteren Zeitpunkt aufrufen

Hi,

braucht hier jemand eine Klasse, mit der man Funktionen unkompliziert zu einem späteren Zeitpunkt aufrufen kann? Interessant ist das z.B., wenn man gerade noch ein Control initialisiert, aber eine bestimmte Aktion erst durchführen kann, wenn es damit fertig ist. Wenn man weiß, dass das in 30 Millisekunden der Fall ist, kann man die Funktion ja dann erst aufrufen. Ein anderer Einsatzzweck ist z.B. der Abbruch von bestimmten Aktionen, wenn sich nach einer vorgegebenen Zeit (z.B. 2 Sekunden) nichts getan hat. Man könnte auch TreeNodes nach 0,5 s Mouse-Hover-Dauer aufklappen oder so. Die Einsatzmöglichkeiten sind sehr vielfältig. Ich habe für meinen Brötchenfinanzierer mal ein größeres Programm entwickelt, in dem diese Klasse entstanden ist und in dem ich sie auch sehr gut einsetzen konnte.

Da die Klasse bereits im Web veröffentlicht ist, spare ich mir mal, sie hier nochmal einzupacken, und gebe gleich den Link darauf:

http://beta.unclassified.de/code/dotnet/delayedcall/

P.S.: Ich hoffe, dass ich den Zweck dieser Sammlung nicht falsch verstanden habe und dass es jemand nützlich findet. 🙂

[EDIT]Neuere Version weiter unten[/EDIT]

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo LonelyPixel,

den Sinn hast du ganz richtig verstanden. Vielen Dank für die Komponente. Auch der Verweis auf deine Webseite geht in Ordnung. Da es aber immer wieder vorkommt, dass URLs schon nach kurzer Zeit nicht mehr erreichbar sind, begrüßen wir es, wenn eine Version der Komponente bei uns hochgeladen wird, damit die Komponente selbst auch so lange "lebt" wie der Thread. Ich habe das - deine Erlaubnis voraussetzend - mal getan.

herbivore

L
LonelyPixel Themenstarter:in
333 Beiträge seit 2007
vor 17 Jahren

Kein Problem. Ich weiß nur nicht, ob ich immer daran denke, das hier zu aktualisieren, wenn ich was dran ändere, was bei meinen öffentlichen Code-Schnipseln durchaus mal vorkommt.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo LonelyPixel,

das musst du auch nicht unbedingt 🙂 Solange der Link funktioniert, gibt es die jeweils aktuellste Version und wenn der Link tot ist, gibt es wenigstens überhaupt noch was.

herbivore

L
LonelyPixel Themenstarter:in
333 Beiträge seit 2007
vor 16 Jahren

In den letzten Tagen habe ich diese Klasse komplett neu geschrieben, um ein paar alte Unschönheiten zu beseitigen.* Die alte Aufrufmethode mit dem new-Operator wurde durch statische Methoden ersetzt, die jetzt gleich im Namen unterscheiden, ob man den Aufruf nur vorbereiten oder gleich starten möchte (Create, Start). Die alte Aufrufmethode ist noch als "veraltet" zugelassen, sodass die Klasse kompatibel sein sollte.

  • Durch die Verwendung von generischen Unterklassen lassen sich Methoden mit bis zu 3 Parametern typsicher und ohne Wrapper-Funktion und Typkonvertierungen von object aufrufen. Nur Rückgabewerte dürfen sie nicht haben, die könnten aber ohnehin nicht verarbeitet werden. Eine Unterstützung für solche Funktionen ließe sich aber auch nachrüsten, ebenso wie die Unterstützung für mehr Parameter.
  • Methodenaufrufe sind jetzt auch asynchron, d.h. in einem ThreadPool-Thread möglich. Dafür gibt es zusätzliche Methoden (CreateAsync, StartAsync), die statt dem System.Windows.Forms.Timer einen System.Timers.Timer verwenden. Ansonsten wird die Methode auch weiterhin im Thread des Aufrufers gestartet. (Entgegen den Aussagen der MSDN haben nach meinen Messungen beide Klassen eine zeitliche Abweichung von max. ± 10 ms.)
  • Alle DelayedCall-Instanzen werden in einer statischen Liste verwaltet, so lange sie laufen. Das sollte ein mögliches vorzeitiges Einsammeln durch den Garbage Collector verhindern, was mir bislang aber noch nie aufgefallen wäre. Man kann aber auch weiterhin selbst Referenzen auf eine Instanz halten, um sie später zu steuern.
  • Die Semantik der Fire-Methode wurde so geändert, dass ein doppelter Aufruf nahe dem geplanten Aufrufzeitpunkt verhindert wird. Um die Callback-Methode jederzeit sofort aufzurufen, sollte man Reset(0) verwenden.
  • Auch wenn es kein üblicher Anwendungsfall ist, sollten die statischen und Instanzmethoden der <code>DelayedCall</code>-Klassen threadsicher sein.

Folgendes Beispiel veranschaulicht die Verwendung von DelayedCall und zeigt ein paar weitere Steuermöglichkeiten.

// Variable to keep track of the instance. This is not required for normal operation.
private DelayedCall dc = null;

private void button1_Click(object sender, EventArgs e)
{
	// Change button text in 2 seconds
	dc = DelayedCall<string>.Start(SetButtonText, "I was clicked", 2000);
}

private void SetButtonText(string newText)
{
	button1.Text = newText;
}

private void HurryUpButton_Click(object sender, EventArgs e)
{
	// Invoke SetButtonText now, if the timeout isn't elapsed yet
	if (dc != null) dc.Fire();

	// Prepare a DelayedCall object for later use
	DelayedCall exitDelay = DelayedCall.Create(Application.Exit, 0);
	// Now start the timeout with 0.5 seconds
	exitDelay.Reset(500);
}

Webseite mit Download, Beispiel und Änderungen: http://beta.unclassified.de/code/dotnet/delayedcall/