C# 在没有CancellationToken的情况下停止任务
我使用的外部库具有C# 在没有CancellationToken的情况下停止任务,c#,async-await,cancellation,C#,Async Await,Cancellation,我使用的外部库具有async方法,但没有CancellationToken重载 现在,我正在使用另一个StackOverflow问题的扩展方法来添加CancellationToken: public async static Task HandleCancellation(this Task asyncTask, CancellationToken cancellationToken) { // Create another task that completes
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://stackoverflow.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;
}
public async static Task HandleCancellation(此任务为asyncTask,CancellationToken CancellationToken)
{
//创建另一个任务,该任务在请求取消时立即完成。http://stackoverflow.com/a/18672893/1149773
TaskCompletionSource tcs=新的TaskCompletionSource();
cancellationToken.Register(()=>
tcs.trysetconceled(),useSynchronizationContext:false);
任务取消任务=tcs.Task;
//创建在异步操作完成时完成的任务,或
//请求取消。
任务准备任务=等待任务。WhenAny(异步任务,取消任务);
//如果取消,请注册续展,以遵守任何未处理的例外情况
//在.NET4.0中,未观察到的任务
//例外情况将终止该过程。
如果(readyTask==cancellationTask)
asyncTask.ContinueWith(=>asyncTask.Exception,
TaskContinuationOptions.OnlyOnFaulted|
TaskContinuationOptions.ExecuteSynchronously);
等待准备任务;
}
但是,底层任务仍然执行到完成。这不是什么大问题,但有时底层任务永远不会完成,并占用我99%的CPU
有没有办法在不终止进程的情况下“终止”任务?正如您所建议的,您可以通过传入
CancellationToken
然后调用cancel
来取消任务
至于如何触发取消,则取决于应用程序的性质
一些可能的情况
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
在案例2中,您可以在启动任务时启动计时器,然后在设定时间后使用CancelAfter
取消任务
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
例如,在案例3中,你可以做一些有进步的事情
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
private void start\u单击(对象发送方,路由目标)
{
...
progressIndicator=新进度(ReportProgress);
cts=新的CancellationTokenSource();
等待MyAsyncTask(progressIndicator,cts.Token);
...
}
void ReportProgress(int值)
{
//如果没有进展,请取消
}
这里有一些有用的链接
,、和.正如您所建议的,您可以通过传入
CancellationToken
然后调用cancel
来取消任务
至于如何触发取消,则取决于应用程序的性质
一些可能的情况
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
在案例2中,您可以在启动任务时启动计时器,然后在设定时间后使用CancelAfter
取消任务
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
例如,在案例3中,你可以做一些有进步的事情
private void cancel_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
await MyAsyncTask(cts.Token);
cts.Cancel();
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
cts = new CancellationTokenSource();
cts.CancelAfter(30000);
await MyAsyncTask(cts.Token);
...
}
private void start_Click(object sender, RoutedEventArgs e)
{
...
Progress<int> progressIndicator = new Progress<int>(ReportProgress);
cts = new CancellationTokenSource();
await MyAsyncTask(progressIndicator, cts.Token);
...
}
void ReportProgress(int value)
{
// Cancel if no progress
}
private void start\u单击(对象发送方,路由目标)
{
...
progressIndicator=新进度(ReportProgress);
cts=新的CancellationTokenSource();
等待MyAsyncTask(progressIndicator,cts.Token);
...
}
void ReportProgress(int值)
{
//如果没有进展,请取消
}
这里有一些有用的链接
、、和。我能想到的唯一方法是更改和管理用于任务的线程的创建。这是一个很大的工作 基本概念是创建自己的实现,使用自己分配的调度程序启动新任务。通过这种方式,您可以将计划程序设置为当前计划程序,并从此任务开始有问题的任务 仍然有一些理由可能不起作用。如果给您带来麻烦的任务使用默认任务计划程序创建了更多任务,您仍然会遇到相同的问题 如果他们使用
async/await
关键字,您的计划程序将保持活动状态
现在,有了自己控制的调度程序,您可以使用终止任何任务
要了解实现的概念,您应该看看。这是调度程序的默认实现
正如我所说,这是一个很大的工作,但我能想到的唯一方法是杀死不能被取消的任务
要让测试运行(如果这样做有效的话),您可能只想实现
ThreadPoolTaskScheduler
为选项提供的行为。因此,为每个任务生成一个新线程。我能想到的唯一方法是更改线程并自己管理用于任务的线程的创建。这是一个很大的工作
基本概念是创建自己的实现,使用自己分配的调度程序启动新任务。通过这种方式,您可以将计划程序设置为当前计划程序,并从此任务开始有问题的任务
仍然有一些理由可能不起作用。如果给您带来麻烦的任务使用默认任务计划程序创建了更多任务,您仍然会遇到相同的问题
如果他们使用async/await
关键字,您的计划程序将保持活动状态
现在,有了自己控制的调度程序,您可以使用终止任何任务
要了解实现的概念,您应该看看。这是调度程序的默认实现
正如我所说,这是一个很大的工作,但我能想到的唯一方法是杀死那个不能完成的任务