Question

I'm developing a class library that implements a protocol stack. There I have an asynchronous operation DoSomething that implements IAsyncResult. The user of this method can use BeginDoSomething and EndDoSomething. So long it's quite a common task.

Now I got the requirement to make the asynchronous operation abortable. I can think of several ways to achieve this, but I'm not sure which one is the best:

  1. Have a CancelDoSomething method besides BeginDoSomething and EndDoSomething. This is not the common asaync pattern and thus not easy to find out for the user of the operation.
  2. According to no. 1: Have a Cancel property
  3. The instance of IAsyncResult that is returned by BeginDoSomething can be casted to DoSomethingAsyncResult. DoSomethingAsyncResult has a Cancel method. Again, this is not the common usage of the async pattern and hardly to know for the "common user" of the class library.
  4. According to no. 3: Have a Cancel property
  5. The instance of IAsyncResult that is returned by BeginDoSomething implements IAbortableAsyncResult: public IAbortableAsyncResult:IAsyncResult { void Abort(); }. For me this seems to be the most elegant way. When the user starts the operation using BeginDoSomething he gets an instance of IAbortableAsyncResult which means that this special feature is prominently introduced to him.

What is the best solution? Are there even more ways to solve this? I prefer no. 5 because it doesn't have a code smell ( at least I didn't recognize until now).

[EDIT]

An approach not relying on TPL/.NET 4 is appreciated to have a solution that is also applicable in legacy code that cannot be ported to the newest version of .NET framework.

[/EDIT]

Was it helpful?

Solution

CancellationToken and CancellationTokenSource were added to .net in 4.0, and form the basis for a common cancellation pattern ever since. Generally, asynchronous methods have an overload which takes a CancellationToken.

Consumers of CancellationTokens may register for a callback when the token is canceled, and use the callback to stop executing. Alternatively, if the task is not particularly long-executing, the IsCanceled property can just be polled intermittently.

The CancellationToken is the interface used by the asynchronous task, the initiator of the task uses a CancellationTokenSource to issue this token, and may then cancel it in the future.

One of the nice things about this approach, other than it becoming a standard way to approach cancellation, is that it is composable. If the task composes several other cancellable asynchronous operations, the same cancellation token can be passed through to them and the cancellation should automatically work itself out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top