我正在使用一个具有异步方法但没有 CancellationToken 重载的外部库。现在我正在使用另一个 StackOverflow 问题中的扩展方法来添加 CancellationTo...
方法但没有 async
的外部库 CancellationToken
。
现在我正在使用另一个 StackOverflow 问题的扩展方法来添加 CancellationToken
:
public async static Task HandleCancellation(this Task asyncTask, CancellationToken cancellationToken)
{
// Create another task that completes as soon as cancellation is requested. http://.com/a/18672893/1149773
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
cancellationToken.Register(() =>
tcs.TrySetCanceled(), useSynchronizationContext: false);
Task cancellationTask = tcs.Task;
// Create a task that completes when either the async operation completes, or
// cancellation is requested.
Task readyTask = await Task.WhenAny(asyncTask, cancellationTask);
// In case of cancellation, register a continuation to observe any unhandled exceptions
// from the asynchronous operation (once it completes). In .NET 4.0, unobserved task
// exceptions would terminate the process.
if (readyTask == cancellationTask)
asyncTask.ContinueWith(_ => asyncTask.Exception,
TaskContinuationOptions.OnlyOnFaulted |
TaskContinuationOptions.ExecuteSynchronously);
await readyTask;
}
但是底层任务仍然执行完成。这不会有什么大问题,但有时底层任务永远无法完成,并消耗了我 99% 的 CPU。
有没有什么办法可以“终止”任务而不终止进程?
有没有什么办法可以“终止”任务而不终止进程?
没有。引用 微软的 博客文章
那么,你能取消不可取消的操作吗?不能。
即使你终止了进程,也不能保证操作本身会停止。 , Task
也称为 promise ,是一种通用结构,表示某些操作的完成,并且不公开有关如何以及在何处执行此操作的信息。据你所知,此操作可能在设备驱动程序、线程、单独的进程、单独的机器或世界另一端的远程服务器上执行。你不能将取消行为注入从未设计为可取消的操作,就像你不能将自毁行为注入从未配备自毁硬件的飞行火箭一样。
我们来看一个例子:
public async Task<int> DoStuffAsync()
{
Process p = new();
p.StartInfo.FileName = @"C:\SomeProgram.exe";
p.Start();
await p.WaitForExitAsync();
return p.ExitCode;
}
如果您启动异步 DoStuffAsync()
操作,然后在 Task
完成之前终止当前进程,将 SomeProgram.exe 继续运行。因此,假设您无法访问源代码 DoStuffAsync
,并且不知道其内部正在做什么,您将无法在启动后采取任何措施来阻止它。您可以做的是要求拥有它的开发人员发布支持取消的新版本,或者搜索更好的库。