In this lesson, you will learn how to design interfaces that allow consumers to safely cancel long-running tasks and track their progress in real-time.
The "Async-Friendly" Contract
When we define an interface for a method that performs heavy lifting—like downloading a large file or processing a database query—simply returning a Task isn't enough. To make an interface truly "async-friendly," we must provide the caller with the power to control the operation’s lifecycle. We achieve this by including two specific parameters: CancellationToken and IProgress<T>.
Designing the Interface
Consider a service that processes bulk data. Without these parameters, the caller is "stuck" waiting until the task finishes. By adding these to our interface, we grant the caller control:
public interface IDataProcessor
{
// The CancellationToken allows the caller to abort the work.
// The IProgress<int> allows the caller to report back percentage updates.
Task ProcessLargeDatasetAsync(
string source,
CancellationToken ct,
IProgress<int> progress);
}
Why This Matters
CancellationToken: If your user closes a window or cancels a request, you don’t want your background thread to continue burning CPU cycles. By passing this token, your implementation can periodically checkct.ThrowIfCancellationRequested()to stop immediately.IProgress<T>: Interfaces are contracts. By acceptingIProgress<int>, your interface explicitly promises to provide feedback, allowing the UI layer to update a progress bar without the interface needing to know that a UI even exists.
Implementing the Behavior
When you implement this interface, you aren't just writing code; you are building a cooperative system. Your method becomes a "good citizen" that listens for signals to stop and provides regular status updates. This keeps your application responsive and gives the user a sense of control, which is the hallmark of a professional-grade asynchronous API.
By standardizing these parameters across your interfaces, you ensure that every background task you create follows the same predictable pattern, making your code easier to maintain and test.
Key Takeaway: An async-friendly interface empowers the caller by providing standard mechanisms for cancellation and progress reporting, turning opaque background tasks into transparent, controllable operations.