2017-10-29 6 views
3

Sagen wir, ich habe ein Label und einen Button. Wenn ich auf die Schaltfläche klicke, wird die Beschriftung auf einen Text gesetzt, sagen Sie "Hallo, Welt!", Und nach 5 Sekunden sollte es verschwinden. Einfach genug, oder? Ich habe die folgende Umsetzung:Inhalt des Labels einstellen und nach 5 Sekunden verschwinden lassen

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    Label = "hello, world!"; 
    await Task.Delay(5_000); 
    Label = string.Empty; 
} 

Lassen Sie uns jetzt sagen, dass ich die zusätzliche Anforderung, dass die Taste auf jeder nachfolgenden Schaltfläche klicken ansprechbar bleiben sollte, und jetzt das Etikett Text sollte hello, world! für die nächsten 5 Sekunden, dh der Etikettentext bleiben sollte für 5 Sekunden seit dem letzten Klicken auf die Schaltfläche bleiben. Das Problem mit dem vorherigen Code ist, dass, wenn ich vor 2,5 Sekunden auf den Button geklickt habe und jetzt erneut klicke, der Labeltext nach 2,5 Sekunden verschwindet. Meine Idee, dies zu lösen, bestand darin, eine Liste von Aufgaben zu führen und die Verzögerungsaufgabe hinzuzufügen und auf die Aufgabenliste zu warten, bevor das Etikett gelöscht wurde. Dies ist die Umsetzung:

private static readonly List<Task> TaskList = new List<Task>(); 
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    Label = "hello, world!"; 
    TaskList.Add(Task.Delay(5_000));  
    await Task.WhenAll(TaskList); 
    if (TaskList.TrueForAll(t => t.IsCompleted)) 
    { 
    TaskList.RemoveAll(t => t.IsCompleted); 
    Label = string.Empty; 
    } 
} 

Soweit ich weiß, diese Umsetzung funktioniert, aber ich weiß nicht viel über die asynchrone Programmierung wissen, damit ich weiß nicht, wie absolut sicher zu sein, es funktioniert.

Fragen:
Wie würden Sie dies umsetzen? Gibt es einen besseren Weg, dies zu implementieren? Ich dachte ursprünglich, dass Task.WhenAll() würde darauf warten, dass alle Aufgaben abgeschlossen sind, aber das scheint nicht der Fall zu sein. Was mache ich falsch?

bearbeitet: Umsetzung mit einer Annullierungs token:

private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); 
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
{ 
    Label = "hello, world!"; 
    _cancellationTokenSource.Cancel(); 
    _cancellationTokenSource = new CancellationTokenSource(); 
    try 
    { 
    await Task.Delay(5_000, _cancellationTokenSource.Token); 
    Label = string.Empty; 
    } catch (TaskCanceledException) { } 
} 
+0

Ich glaube, der Begriff Sie suchen, ist, wie die Ereignishandler der Schaltfläche klicken drosseln – Nkosi

+0

@Nkosi Können Sie ein wenig mehr sagen? – asfeynman

Antwort

3

Abbrechen Gerade die anstehenden Aufgabe await Task.Delay(5_000, cancelToken); ein CancellationToken verwenden und einen neuen sofort starten.

+0

Ich habe eine Implementierung mit einem Kündigungs-Token hinzugefügt, können Sie das kommentieren? Vielen Dank. – asfeynman

+0

@asfeynman Ihr Code sieht im Allgemeinen gut aus, aber '_cancellationTokenSource' sollte nicht statisch sein. – Kostya

+0

Großartig, ich werde das reparieren. – asfeynman

Verwandte Themen