Skip to content

Instantly share code, notes, and snippets.

@danielmarbach
Last active October 11, 2018 21:04
Show Gist options
  • Save danielmarbach/4485bd542c2a9db6784f4b0ff7fbbb98 to your computer and use it in GitHub Desktop.
Save danielmarbach/4485bd542c2a9db6784f4b0ff7fbbb98 to your computer and use it in GitHub Desktop.
public static class TimeboxExtensions
{
public static async Task Timebox(this IEnumerable<Task> tasks, TimeSpan timeoutAfter, string messageWhenTimeboxReached)
{
using (var tokenSource = new CancellationTokenSource())
{
var delayTask = Task.Delay(Debugger.IsAttached ? TimeSpan.MaxValue : timeoutAfter, tokenSource.Token);
var allTasks = Task.WhenAll(tasks);
var returnedTask = await Task.WhenAny(delayTask, allTasks).ConfigureAwait(false);
tokenSource.Cancel();
if (returnedTask == delayTask)
{
throw new TimeoutException(messageWhenTimeboxReached);
}
await allTasks.ConfigureAwait(false);
}
}
}
[TestFixture]
public class TimeboxExtensionsTests
{
[Test]
public void ThrowsTimeoutException()
{
var allTasks = new[] { Task.Delay(20), Task.Delay(50)};
var exception = Assert.ThrowsAsync<TimeoutException>(async () => { await allTasks.Timebox(TimeSpan.FromMilliseconds(20), "Problem due to timeout"); });
Assert.AreEqual("Problem due to timeout", exception.Message);
}
[Test]
public void DoesNotThrowWhenCompleted()
{
var allTasks = new[] {Task.Delay(20), Task.Delay(50)};
Assert.DoesNotThrowAsync(async () => { await allTasks.Timebox(TimeSpan.FromMilliseconds(100), "Problem"); });
}
[Test]
public void ThrowsExceptionOfTasks()
{
var invalidOperationException = new InvalidOperationException();
var allTasks = new[] { Task.Delay(20), Task.Delay(50), Task.Delay(50).ContinueWith(t => throw invalidOperationException) };
var exception = Assert.ThrowsAsync<InvalidOperationException>(async () => { await allTasks.Timebox(TimeSpan.FromMilliseconds(100), "Problem"); });
Assert.AreSame(invalidOperationException, exception);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment