Home > other >  Using CancellationToken to quit an async method after a timeout
Using CancellationToken to quit an async method after a timeout

Time:01-14

Now that the .abort() is deprecated using cancellation tokens is the recommended method for closing your async threads, but I can't figure how to do this after a timeout. It's just a logic problem that I'm having a hard time thinking through...

I'm mounting a network drive programmatically but I can't seem to figure how I can use a cancellation token to make the entire operation quit after x amount of time so it's not just blocking up a thread if it hangs for whatever reason (the operation often just goes silent if it can't find the address rather than just stopping or crashing something).

Code for tokensource is this:

using var cts = new CancellationTokenSource();
cts.CancelAfter(2000); //timeout value
Task<bool> attempt_mounting = Utility.Windows.System.PerformTargetLocationMounting(ADDRESS, "X", cts.Token);
primary_connection_success = await attempt_mounting;

and the code for the bit that I want to be cancelled after the timeout is this:

internal static async Task<bool> PerformTargetLocationMounting(string address, string drive, CancellationToken ct)
            {
                Console.WriteLine("[*] Attempting target mounting");
               
                return await Task.Run(async () =>
                {
                    try
                    {
                        ct.ThrowIfCancellationRequested(); //currently unsure on what to do with this
                        await Task.Delay(5000).ConfigureAwait(false); //and this is just to force it to cancel so I can try things out
                        NetworkDrive.MapNetworkDrive(drive, address);
                        return true;
                    }
                    catch
                    {
                        Console.WriteLine("[!] Untraced mounting error.");
                        return false;
                    }
               
                });
            }

I can't figure how to get it so that I can have the cancellationtoken called without having to continually poll using a while true, and as the map network drive is certainly not something I want to be continually calling, I'm not sure how to go about this...

CodePudding user response:

You need to pass the CancellationToken into whatever method needs to be cancelled - in this case, NetworkDrive.MapNetworkDrive.

However, it's likely that the method won't take a cancellation token; a lot of file system-related APIs do not permit cancellation. In that case, you have two options:

  1. Live with it. You can use WaitAsync or similar to cancel the waiting of the task and just let the MapNetworkDrive complete or not in the future.
  2. Wrap the logic into a separate process and kill that process when you need to cancel.

CodePudding user response:

You want to use a CancellationToken in a non-cooperative fashion. This is not how CancellationTokens are intended to be used in general. Since you are calling an API that does not accept a CancellationToken, you have no way of terminating cooperatively this API. So there is no nice and clean solution to your problem. Invoking the API in a separate process and then killing the process if it runs for too long, is a solution that preserves solely the integrity of your process, but it doesn't guarantee that the integrity of your application as a whole will remain intact. For example files/databases on which your application depends might become corrupted as a result of killing the other process.

You could check out this answer that shows how to use the Thread.Interrupt method in combination with a CancellationToken. Calling Thread.Interrupt interrupts a thread only when it's in a waiting state, so if a thread is spinning in a tight loop the Interrupt will have no effect. Also interrupting a thread does not guarantee that the managed/unmanaged resources associated with the interrupted work will be cleaned. Nevertheless you could give it a try, see if it solves the problem, and make your own judgment about whether it can be trusted to run in a production environment.

  • Related