Friday, 30 June 2017
Richard Blewett
5 minute read
One thing I only noticed recently is that CTS implements IDisposable
. It previously hadn’t occurred to me that I would need to Dispose a CTS. Looking at the implementation in DotPeek I saw there were a few things that would require cleanup. So, dutifully, I put the calls in my code – only to see it sometimes blow up spectacularly with an ObjectDisposedException
. To understand what was happening consider the following code:
public class CancellableExecutor
{
CancellationTokenSource cts = new CancellationTokenSource();
public Task Execute(Action<CancellationToken> action)
{
return Task.Run(() => action(cts.Token), cts.Token);
}
public void Cancel()
{
cts.Cancel();
cts.Dispose();
cts = new CancellationTokenSource();
}
}
Here we have a class whose job it is to be able to run a series of actions and cancel any outstanding on request. As you can imagine this type of object is intended to be used in asynchronous execution and therefore new pieces of work could be getting requested for execution while someone else is going to cancel.
The problem is that cts.Token
throws an ObjectDisposedException
if accessed after Dispose
has been called. Now, I fully understand why I shouldn’t be able to, say, call Cancel
on the CTS once it is disposed, but accessing a value that allows no more interaction than if I had accessed it just before Dispose
was called seems very odd. Because of this, let’s call it a "feature", we need to write the above code in the following, non-obvious way:
public class CancellableExecutor
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = CancellationToken.None;
public CancellableExecutor()
{
token = cts.Token;
}
public Task Execute(Action<CancellationToken> action)
{
return Task.Run(() => action(token), token);
}
public void Cancel()
{
cts.Cancel();
cts.Dispose();
cts = new CancellationTokenSource();
token = cts.Token;
}
}
As you can see, we have to cache the CancellationToken
and pass that around. Although this works, I really wish we could access the Token property after Dispose is called.
Last updated: Monday, 12 June 2023
Director
He/him
Richard is a Director at Rock Solid Knowledge.
We're proud to be a Certified B Corporation, meeting the highest standards of social and environmental impact.
+44 333 939 8119