Das ist also uralt, aber es gibt eine viel bessere moderne Lösung. Nicht sicher, welche Version von c#/.NET erforderlich ist, aber dies ist, wie ich es tun:
... Other method code not relevant to the question.
// a token source that will timeout at the specified interval, or if cancelled outside of this scope
using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutTokenSource.Token);
async Task<MessageResource> FetchAsync()
{
try
{
return await MessageResource.FetchAsync(m.Sid);
} catch (TaskCanceledException e)
{
if (timeoutTokenSource.IsCancellationRequested)
throw new TimeoutException("Timeout", e);
throw;
}
}
return await Task.Run(FetchAsync, linkedTokenSource.Token);
その CancellationTokenSource
Konstruktor nimmt eine TimeSpan
der dazu führt, dass das Token nach Ablauf dieses Intervalls abgebrochen wird. Sie können dann Ihren asynchronen (oder synchronen) Code in einen weiteren Aufruf von Task.Run
und übergibt das Timeout-Token.
Dies setzt voraus, dass Sie ein Stornierungs-Token übergeben (die token
Variable). Wenn Sie die Aufgabe nicht getrennt von der Zeitüberschreitung abbrechen müssen, können Sie einfach timeoutTokenSource
direkt. Andernfalls erstellen Sie linkedTokenSource
, die bei einer Zeitüberschreitung abgebrochen wird, ou wenn sie sonst annulliert wird.
Wir fangen dann einfach OperationCancelledException
und prüfen, welches Token die Ausnahme ausgelöst hat, und eine TimeoutException
wenn eine Zeitüberschreitung dies ausgelöst hat. Andernfalls lösen wir einen Re-Throw aus.
Außerdem verwende ich hier lokale Funktionen, die in C# 7 eingeführt wurden, aber Sie könnten problemlos Lambda- oder tatsächliche Funktionen verwenden, um denselben Effekt zu erzielen. In ähnlicher Weise führte c# 8 eine einfachere Syntax für using-Anweisungen, aber diese sind einfach genug, um neu zu schreiben.