Ich habe ein Problem beim ordnungsgemäßen Abbrechen einer asynchronen Aufgabe festgestellt.Gibt es eine ordnungsgemäße Möglichkeit, eine asynchrone Aufgabe abzubrechen?
Hier ist ein Entwurf.
Mein Einstiegspunkt führt zwei asynchrone Aufgaben aus. Die erste Aufgabe erledigt "lange" Arbeit und die zweite Aufgabe bricht sie ab.
Einstiegspunkt:
private static void Main()
{
var ctc = new CancellationTokenSource();
var cancellable = ExecuteLongCancellableMethod(ctc.Token);
var cancelationTask = Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine("[Before cancellation]");
ctc.Cancel();
});
try
{
Task.WaitAll(cancellable, cancelationTask);
}
catch (Exception e)
{
Console.WriteLine($"An exception occurred with type {e.GetType().Name}");
}
}
Methode, die Aufgabe zurückgegeben-able Abbrechen
private static Task ExecuteLongCancellableMethod(CancellationToken token)
{
return Task.Run(() =>
{
token.ThrowIfCancellationRequested();
Console.WriteLine("1st");
Thread.Sleep(1000);
Console.WriteLine("2nd");
Thread.Sleep(1000);
Console.WriteLine("3rd");
Thread.Sleep(1000);
Console.WriteLine("4th");
Thread.Sleep(1000);
Console.WriteLine("[Completed]");
}, token);
}
Mein Ziel '1.' zu stoppen, ist das Schreiben, '2.', '3.' sofort nach Absage wird angerufen. Aber ich habe folgende Ergebnisse:
1st
2nd
3rd
[Before cancellation]
4th
[Completed]
Aus offensichtlichen Grund, warum ich nicht eine Ausnahme erhalten, die auslöst, wenn Annullierung angefordert wird. Also habe ich versucht Methode neu zu schreiben, wie folgend:
private static Task ExecuteLongCancellableAdvancedMethod(CancellationToken token)
{
return Task.Run(() =>
{
var actions = new List<Action>
{
() => Console.WriteLine("1st"),
() => Console.WriteLine("2nd"),
() => Console.WriteLine("3rd"),
() => Console.WriteLine("4th"),
() => Console.WriteLine("[Completed]")
};
foreach (var action in actions)
{
token.ThrowIfCancellationRequested();
action.Invoke();
Thread.Sleep(1000);
}
}, token);
}
Und jetzt habe ich, was ich will:
1st
2nd
[Before cancellation]
3rd
An exception occurred with type AggregateException
aber ich denke, die Schaffung einer Sammlung von Action-Delegierten und Looping durch nicht das bequemste ist Möglichkeit, mit meinem Problem umzugehen.
Also, was ist der richtige Weg, es zu tun? Und warum muss ich mein Abbruch-Token in die Task.Run-Methode als zweites Argument übergeben?
Wenn die Stornierung für die Token bereits angefordert worden ist, 'Task.Run' nicht die Delegierten läuft auf all –
Sie müssen explizit nennen' token.ThrowIfCancellationRequested(); 'an jedem Ort, wo Sie wollen die Ausführung, um tatsächlich stornierbar zu sein. Also im ersten Beispiel vor jeder 'Console.WriteLine'. –
Ich empfehle dringend, dass Sie auch auf die ContinueWith-Methode nachlesen, da Sie nach dem "richtigen" Weg gefragt haben. Ich denke, Sie werden sich mit ContinueWith und TaskContinuationOptions.NotOnCanceled vertraut machen. Hier ist ein Link mit mehr hilfreiche Informationen: https://social.msdn.microsoft.com/Forums/en-US/310782d8-aadf-4841-a309-23abff407d9a/cancellation-using-exception-to-control-application-flow? forum = Parallelextensions – Jace