Search code examples
c#multithreadingasynchronousasync-awaitcancellation-token

How could I abort an awaited task?


I have recently very quickly learned that all a Cancellation token, in my context, is worth is to prevent the task from being scheduled. I have long running, single method tasks that I need to abort in the awaited task. How can I achieve this?

My first idea is to let rip another thread for the long running method, but above that have a loop that keeps checking if Cancellation.IsCancelled == true, and when it is true, I abort the thread hosting the long running method.

Is this bad? Is there some other way?

BTW, my long running task is a single method, so I can either check the cancellation token before it starts running, or after it's run, leaving me no opportunity to stop the long running method before it finishes, e.g, collection all FileInfo objects for every file on drive C:! This is the long running code:

FileInfos = Mapper.Map<ObservableCollection<FileInfoViewModel>>(dirInfo.GetFiles($"*.{ext.TrimStart('.')}", SearchOption.AllDirectories));

I could split that into two calls, and check the token between them, but that won't have much effect, or I can rewrite CLR code into my own, and manually use loops that check the token. That will work, but it smells very bad.


Solution

  • The underlying system API used for enumerating file system entities already supports cancellation - you just have to make sure to use the correct managed API.

    DirectoryInfo.GetFiles will transform the enumerable to an array - which means it only returns when all the data has been collected. On the other hand, DirectoryInfo.EnumerateFiles will expose the enumerable directly, and you can easily stop evaluation at any point.

    There's still a few bits that will not be interruptible, but Thread.Abort wouldn't help you there anyway - Thread.Abort only kills threads when they're in managed code, and all the things that actually take time are native, using the FindFirstFile/FindNextFile APIs.