繁体   English   中英

CancellationTokenSource 不取消任务

[英]CancellationTokenSource does not cancel the task

对于一个启动任务而另一个停止该任务的场景,我有两个按钮。

   // this is the property which is used to cancel the task
   CancellationTokenSource cTokenSource;

private async void OnReadCommand()
{
   cTokenSource = new CancellationTokenSource();
   ReadAction();
}


private async void ReadAction()
{
   Task.Factory.StartNew(() => {
       while (true)
       {
           Task.Delay(TimeSpan.FromSeconds(2)).Wait();
        //writing in debug console
           Debug.WriteLine($"Some Random Nos : {Guid.NewGuid().ToString()}");
        //sending it to the ui for testing
           uiContext.Send(x => MessageArea2Content.Message = Guid.NewGuid().ToString(), null);
       }
   },cTokenSource.Token);
}
       
private async void OnCancelCommand()
{
   // it's used to cancel the task
   cTokenSource.Cancel();
}

我的应用程序是 wpf 并使用 mvvm 模式和棱镜库。 在调用 OnCancelCommand 时,任务在后台运行并打印 GUID。 我必须仅在 OnCancelCommand 上取消任务。

您需要自己实现退出循环的代码:

private async void ReadAction()
{
    Task.Factory.StartNew(() => {
        while (true)
        {
            Task.Delay(TimeSpan.FromSeconds(2)).Wait();
            //writing in debug console
            Debug.WriteLine($"Some Random Nos : {Guid.NewGuid().ToString()}");
            //sending it to the ui for testing
            uiContext.Send(x => MessageArea2Content.Message = Guid.NewGuid().ToString(), null);
            
            cTokenSource.Token.ThrowIfCancellationRequested();
        }
    },cTokenSource.Token);
}

或者

private async void ReadAction()
{
    Task.Factory.StartNew(() => {
        while (true)
        {
            Task.Delay(TimeSpan.FromSeconds(2)).Wait();
            //writing in debug console
            Debug.WriteLine($"Some Random Nos : {Guid.NewGuid().ToString()}");
            //sending it to the ui for testing
            uiContext.Send(x => MessageArea2Content.Message = Guid.NewGuid().ToString(), null);
            
            if (cTokenSource.Token.IsCancellationRequested)
            {
                break; // or return;
            }
        }
    },cTokenSource.Token);

您可以在文档任务 Class中找到使用示例。 将 CancellationToken 传递给 StartNew 方法的唯一好处是,如果在任务开始之前取消源,它可以自动为您取消任务。 但是,要在运行期间取消它,您需要自己编写逻辑代码。 这是关于https://stackoverflow.com/questions/48312544/whats-the-benefit-of-passing-a-cancellationtoken-as-a-parameter-to-task-run#:~:text=的另一个好读物在%20summary%2C%20providing%20the%20cancellation,to%20start%20running%20the%20task

此外,我建议您在 StartNew 中执行的逻辑中使用 await ,这样您就不会失去异步的好处:

private async void ReadAction()
{
    Task.Factory.StartNew(async () => {
        while (true)
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            //writing in debug console
            Debug.WriteLine($"Some Random Nos : {Guid.NewGuid().ToString()}");
            //sending it to the ui for testing
            uiContext.Send(x => MessageArea2Content.Message = Guid.NewGuid().ToString(), null);
            
            if (cTokenSource.Token.IsCancellationRequested)
            {
                break; // or return;
            }
        }
    },cTokenSource.Token)

这样线程将不再被阻塞,并且将在调用延迟期间被释放。

暂无
暂无

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

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