Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在没有CancellationToken的情况下停止任务_C#_Async Await_Cancellation - Fatal编程技术网

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
来取消任务

至于如何触发取消,则取决于应用程序的性质

一些可能的情况

  • 继续,直到单击“取消”
  • 在固定时间后取消
  • 如果在固定时间内没有进展,请取消
  • 例如,在案例1中,您只需从“取消”按钮取消任务

    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
    来取消任务

    至于如何触发取消,则取决于应用程序的性质

    一些可能的情况

  • 继续,直到单击“取消”
  • 在固定时间后取消
  • 如果在固定时间内没有进展,请取消
  • 例如,在案例1中,您只需从“取消”按钮取消任务

    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
    关键字,您的计划程序将保持活动状态

    现在,有了自己控制的调度程序,您可以使用终止任何任务

    要了解实现的概念,您应该看看。这是调度程序的默认实现

    正如我所说,这是一个很大的工作,但我能想到的唯一方法是杀死那个不能完成的任务