繁体   English   中英

使用 CancellationToken 在超时后退出异步方法

[英]Using CancellationToken to quit an async method after a timeout

既然 the.abort() 已被弃用,使用取消标记是关闭异步线程的推荐方法,但我不知道如何在超时后执行此操作。 这只是一个逻辑问题,我很难想通......

我正在以编程方式安装 a.network 驱动器,但我似乎无法弄清楚如何使用取消令牌使整个操作在 x 时间后退出,所以它不仅仅是阻塞线程,如果它出于任何原因挂起(如果找不到地址,操作通常会停止,而不是停止或崩溃)。

tokensource 的代码是这样的:

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;

超时后我想取消的代码是这样的:

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;
                    }
               
                });
            }

我不知道如何获得它,这样我就可以调用 cancellationtoken 而不必使用 while true 连续轮询,并且由于 map.network 驱动器肯定不是我想要连续调用的东西,我不确定如何go关于这个......

您需要将CancellationToken传递给需要取消的任何方法 - 在本例中为NetworkDrive.MapNetworkDrive

但是,该方法很可能不会使用取消令牌; 许多与文件系统相关的 API 不允许取消。 在这种情况下,您有两个选择:

  1. 忍受它。 您可以使用WaitAsync或类似的方法来取消任务的等待,并让MapNetworkDrive完成或不完成。
  2. 将逻辑包装到一个单独的进程中,并在需要取消时终止该进程。

您希望以非合作方式使用CancellationToken 不是通常使用CancellationToken的方式。 由于您调用的是不接受CancellationToken的 API,因此您无法合作终止此 API。因此,您的问题没有完美而干净的解决方案。 在单独的进程中调用 API 然后在运行时间过长的情况下终止进程,这是一种仅保留进程完整性的解决方案,但它不能保证整个应用程序的完整性保持不变。 例如,您的应用程序所依赖的文件/数据库可能会因终止其他进程而损坏。

您可以查看此答案,其中显示了如何将Thread.Interrupt方法与CancellationToken结合使用。 只有在等待 state 时调用Thread.Interrupt才会中断线程,因此如果线程在紧密循环中旋转,则Interrupt将不起作用。 此外,中断线程并不能保证与中断工作关联的托管/非托管资源将被清除。 不过,您可以尝试一下,看看它是否解决了问题,并自行判断是否可以信任它在生产环境中运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM