With the following code you can create a CancellationTokenSource that will signal cancellation on dispose. This provides an alternative to having to wrap a normal CancellationTokenSource in a try finally block.
Code
public class AutoCancellationTokenSource : CancellationTokenSource
{
private bool _isDisposed;
public AutoCancellationTokenSource()
{
}
public AutoCancellationTokenSource(params CancellationToken[] linkedTokens)
{
foreach (var linkedToken in linkedTokens)
if (linkedToken.IsCancellationRequested)
TryCancel();
else
linkedToken.Register(TryCancel, false);
}
protected override void Dispose(bool disposing)
{
if (_isDisposed)
return;
TryCancel();
base.Dispose(disposing);
_isDisposed = true;
}
private void TryCancel()
{
if (!_isDisposed && !IsCancellationRequested)
Cancel();
}
}
Tests
public class AutoCancellationTokenSourceTests
{
[Fact]
public void StandardTest()
{
CancellationToken token;
using (var source = new CancellationTokenSource())
token = source.Token;
Assert.False(token.IsCancellationRequested);
}
[Fact]
public void AutoTest()
{
CancellationToken token;
using (var source = new AutoCancellationTokenSource())
token = source.Token;
Assert.True(token.IsCancellationRequested);
}
[Fact]
public void LinkedTest()
{
using (var standardSource = new CancellationTokenSource())
using (var autoSource = new AutoCancellationTokenSource(
standardSource.Token))
{
Assert.False(autoSource.IsCancellationRequested);
standardSource.Cancel();
Assert.True(autoSource.IsCancellationRequested);
}
}
[Fact]
public void LinkedPreCancelTest()
{
using (var standardSource = new CancellationTokenSource())
{
standardSource.Cancel();
using (var autoSource = new AutoCancellationTokenSource(
standardSource.Token))
{
Assert.True(autoSource.IsCancellationRequested);
}
}
}
[Fact]
public void MultipleLinkedTest()
{
using (var standardSource1 = new CancellationTokenSource())
using (var standardSource2 = new CancellationTokenSource())
using (var autoSource = new AutoCancellationTokenSource(
standardSource1.Token,
standardSource2.Token))
{
Assert.False(autoSource.IsCancellationRequested);
standardSource1.Cancel();
Assert.True(autoSource.IsCancellationRequested);
standardSource2.Cancel();
Assert.True(autoSource.IsCancellationRequested);
}
}
}
Enjoy,
Tom
No comments:
Post a Comment