Timeout-Muster für aufgabenbasierte asynchrone Methode in C #

Soweit ich weiß, gibt es zwei mögliche Muster, um ein Timeout für aufgabenbasierte asynchrone Methoden zu implementieren:

Eingebaute Zeitüberschreitung
public Task DoStuffAsync(TimeSpan timeout)

Dieser Ansatz ist schwieriger zu implementieren, da es nicht einfach ist, ein @ zu implementiere global Timeout für den gesamten Aufrufstapel. Ein Web-API-Controller empfängt beispielsweise eine HTTP-Anforderung und ruft @ auDoStuffAsync, und der Anrufer möchte eine globale Zeitüberschreitung von 3 Sekunden.

Das heißt, jeder innere asynchrone Methodenaufruf muss den Abzug der bereits verwendeten Zeit erhalten ...

Keine eingebaute Zeitüberschreitung
public Task DoStuffAsync(CancellationToken cancellationToken)

..........

CancellationTokenSource cancellationSource = new CancellationTokenSource();
Task timeoutTask = Task.Delay(3000);

if(await Task.WhenAny(DoStuffAsync(cancellationTokenSource), timeoutTask) == timeoutTask)
{
     cancellationSource.Cancel();

     throw new TimeoutException();
}

Dies scheint das zuverlässigste und am einfachsten zu implementierende Muster zu sein. Der erste Aufrufer definiert ein globales Timeout, und wenn estime outs, alle ausstehenden Vorgänge werden abgebrochen. Außerdem wird dem unmittelbaren Anrufer ein Abbruchtoken bereitgestellt, und interne Anrufe verwenden dieselbe Abbruchtokenreferenz. Wenn der Top-Anrufer eine Zeitüberschreitung hat, kann er daher jeden Arbeitsthread abbrechen.

Die ganze Frage

Gibt es ein Muster, das mir fehlt, oder bin ich in der richtigen Weise, wenn ich APIs mit dem @ entwicklkeine eingebaute Zeitüberschreitung?