As stated in this existing post, the Thread.Abort()
is (severely) deprecated.
A most elegant way of doing this would be to use cancellation token on async
Tasks.
The only drawback is it does not provide any notifications and you have to monitor it yourself using IsCancellationRequested
or ThrowIfCancellationRequested
. But on the other hand it is quite handy and easy to accomplish.
A very basic sample:
public class TaskCompletionTests
{
private readonly ITestOutputHelper _testOutputHelper;
public TaskCompletionTests(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
[Fact]
public async Task TerminateOtherWhenOneCompleted()
{
// Arrange
var cancellationSource = new CancellationTokenSource();
var waitForCompletionDelay = TimeSpan.FromSeconds(2);
var executionWaitingDelay = TimeSpan.FromSeconds(3);
var smallerWaitingDelay = TimeSpan.FromSeconds(1);
// Act
var taskOne = Task.Run(DoSomething("T1", executionWaitingDelay, cancellationSource), cancellationSource.Token);
var taskTwo = Task.Run(DoSomething("T2", smallerWaitingDelay, cancellationSource), cancellationSource.Token);
await Task.WhenAny(taskOne, taskTwo);
cancellationSource.Cancel();
await Task.Delay(waitForCompletionDelay);
}
private Func<Task> DoSomething(string label, TimeSpan waitingDuration, CancellationTokenSource cancellationSource)
{
return async () =>
{
try
{
// do the thing
_testOutputHelper.WriteLine($"{label} working ...");
// wait a bit ...
await Task.Delay(waitingDuration, cancellationSource.Token);
// checking for cancellation
cancellationSource.Token.ThrowIfCancellationRequested();
// do more things ...
_testOutputHelper.WriteLine($"{label} completed.");
}
catch (OperationCanceledException)
{
_testOutputHelper.WriteLine($"{label} was aborted");
}
};
}
}
And output will be
T1 working ... T2 working ... T2 completed. T1 was aborted
You can change the wait duration to test that having T1 completed first will also work.
Hopes this helps.