标签: cancellationtokensource

如何找出一个物体已被处置?

我有一个多线程应用程序,一个CancellationToken用作共享对象.每个线程都可以触发它以告诉其他线程该作业被取消.然后一个线程进行清理并像这样处理每个对象CancellationToken.然后,如果线程尝试使用它,则会引发异常:

CancellationTokenSource已被处理.

在使用之前如何找到对象?

c# dispose cancellationtokensource

6
推荐指数
1
解决办法
2万
查看次数

在没有ThrowIfCancellationRequested的情况下停止任务

我有一个我想要取消的任务.

执行此操作的常规方法是使用CancellationToken.

this.task = new SpecialTask(() =>
{
    for (int i = 0; i < ushort.MaxValue; i++)
    {
        CancelToken.ThrowIfCancellationRequested();
        Console.WriteLine(i);
    }
}, this.CancelToken);
Run Code Online (Sandbox Code Playgroud)

然而,在现实世界中,事情从未如此简单.我们的异步代码无法循环,它看起来像这样:

this.task = new SpecialTask(() =>
{
    CancelToken.ThrowIfCancellationRequested();
    Operation1();

    CancelToken.ThrowIfCancellationRequested();
    Operation267(CancelToken);

    CancelToken.ThrowIfCancellationRequested();
    object232.Operation345();

    CancelToken.ThrowIfCancellationRequested();
    object99.Operation44(CancelToken);

    CancelToken.ThrowIfCancellationRequested();
    Operation5(CancelToken);

    ...

    CancelToken.ThrowIfCancellationRequested();
    Operation...n(CancelToken);

}, this.CancelToken);
Run Code Online (Sandbox Code Playgroud)

我使用随机数作为对象和方法名称来表明无法创建任何循环.

最困扰的是我必须CancelToken.ThrowIfCancellationRequested()一遍又一遍地写同样的东西.

并且,好像这还不够,我必须拖拽CancellationToken我的代码只是为了能够在适当的时候停止长时间运行 - 根据微软的说法.

话虽如此,有没有办法可以免除这些重复的电话,这会使我的代码中毒?

我们也知道,使用时

try
{
    task.Wait(cancelToken);
}
catch(OperationCancelledException)
{
}
Run Code Online (Sandbox Code Playgroud)

一个OperationCancelledException被抛出和捕获的Wait方法.但是,如果没有CancelToken.ThrowIfCancellationRequested()检查,则任务执行的长操作不会停止.

有没有办法在等待时捕获到异常时停止内部操作?

c# multithreading task cancellationtokensource

6
推荐指数
1
解决办法
1606
查看次数

当我在异步方法中调用CancellationTokenSource的Cancel方法时,为什么不取消任务?

我创造了一个小包装CancellationTokenCancellationTokenSource.我遇到的问题是CancelAsync方法CancellationHelper不能按预期工作.

我遇到了这个ItShouldThrowAExceptionButStallsInstead方法的问题.要取消正在运行的任务,它会调用await coordinator.CancelAsync();,但该任务实际上没有被取消,并且不会引发异常task.Wait

ItWorksWellAndThrowsException似乎运行良好而且使用coordinator.Cancel,这根本不是异步方法.

当我CancellationTokenSource在异步方法中调用Cancel方法时,为什么没有取消任务的问题是什么?

不要让waitHandle你迷惑,这只是为了不让任务提前完成.

让代码说明一切:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace TestCancellation
{
    class Program
    {
        static void Main(string[] args)
        {
            ItWorksWellAndThrowsException();
            //ItShouldThrowAExceptionButStallsInstead();
        }

        private static void ItShouldThrowAExceptionButStallsInstead()
        {
            Task.Run(async () =>
            {
                var coordinator = new CancellationHelper();
                var waitHandle = new ManualResetEvent(false);

                var task = Task.Run(() =>
                {
                    waitHandle.WaitOne();

                    //this works well though - …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous task cancellationtokensource cancellation-token

6
推荐指数
1
解决办法
4803
查看次数

如何使用CancellationToken取消任务?

所以我有这个代码:

//CancelationToken
CancellationTokenSource src = new CancellationTokenSource();
CancellationToken ct = src.Token;
ct.Register(() => Console.WriteLine("Abbruch des Tasks"));
//Task
Task t = new Task(() =>
{
    System.Threading.Thread.Sleep(1000);
    if (ct.IsCancellationRequested)
    {
        try
        {
            //Throw
            ct.ThrowIfCancellationRequested();                        
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine(
                "ThrowIfCancellationRequested() liefert eben eine Exception");
        }
    }             

}, ct);
//Run Task and Cancel
t.Start();
src.CancelAfter(350);
t.Wait();

// Get Information
Console.WriteLine("Canceled: {0} . Finished: {1} . Error: {2}",
                    t.IsCanceled, t.IsCompleted, t.IsFaulted);
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下我取消了我的任务,但我的输出最后是:"取消:假.完成:真.错误:错误"

在我看来,它应该是"取消:真实.完成:假".为什么我得到这个结果?因为我试图抓住异常?

我试过没有try-catch块,但是由于OperationCanceledException,我的程序停止了.有人能帮助我吗?

c# task task-parallel-library cancellationtokensource

6
推荐指数
1
解决办法
3314
查看次数

单元测试异步方法:如何显式断言内部任务被取消

我最近编写了一个异步方法,调用外部长时间运行的异步方法,所以我决定通过CancellationToken启用取消.该方法可以同时调用.

实现结合了Stephen Cleary的书" Concurrency in C#Cookbook "中描述的指数退避超时技术,如下所示;

/// <summary>
/// Sets bar
/// </summary>
/// <param name="cancellationToken">The cancellation token that cancels the operation</param>
/// <returns>A <see cref="Task"/> representing the task of setting bar value</returns>
/// <exception cref="OperationCanceledException">Is thrown when the task is cancelled via <paramref name="cancellationToken"/></exception>
/// <exception cref="TimeoutException">Is thrown when unable to get bar value due to time out</exception>
public async Task FooAsync(CancellationToken cancellationToken)
{
    TimeSpan delay …
Run Code Online (Sandbox Code Playgroud)

.net c# unit-testing async-await cancellationtokensource

6
推荐指数
1
解决办法
3356
查看次数

如何使用CancellationTokenSource关闭另一个线程上的对话框?

这与我的其他问题如何取消后台打印有关.

我试图更好地理解CancellationTokenSource模型以及如何跨线程边界使用它.

我有一个主窗口(在UI线程上)后面的代码:

 public MainWindow()
        {
            InitializeComponent();

            Loaded += (s, e) => {
                DataContext = new MainWindowViewModel();
                Closing += ((MainWindowViewModel)DataContext).MainWindow_Closing;

            };
        }
Run Code Online (Sandbox Code Playgroud)

它在关闭时正确调用CloseWindow代码:

 private void CloseWindow(IClosable window)
        {
            if (window != null)
            {
                windowClosingCTS.Cancel();
                window.Close();
            }
        }
Run Code Online (Sandbox Code Playgroud)

通过选择菜单项,在后台线程上创建第二个窗口:

    // Print Preview
    public static void PrintPreview(FixedDocument fixeddocument, CancellationToken ct)
    {
        // Was cancellation already requested? 
        if (ct.IsCancellationRequested)
              ct.ThrowIfCancellationRequested();

               ............................... 

            // Use my custom document viewer (the print button is removed).
            var previewWindow = new PrintPreview(fixedDocumentSequence);

            //Register the cancellation procedure …
Run Code Online (Sandbox Code Playgroud)

c# wpf multithreading cancellationtokensource

6
推荐指数
1
解决办法
704
查看次数

HttpClient取消不会杀死底层TCP调用

我正在尝试将HttpClient调用的默认超时设置为5秒.

我通过这样做了CancellationTokenSource.

这是相关的代码:

var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(TimeSpan.FromSeconds(5));
var result = _httpClient.SendAsync(request, cancellationToken.Token);
Run Code Online (Sandbox Code Playgroud)

按照调用代码获取"任务被取消"错误(我在.NET 4.7控制台应用程序中测试)的预期工作,但我注意到在Fiddler中请求仍然运行1分钟,直到它最终放弃:

在此输入图像描述

有人可以解释这种行为吗?

我希望在触发取消时基础请求也会被取消.

_httpClient 实例化如下: new HttpClient { BaseAddress = baseAddress }

我知道有Timeout设置,但不确定我是否应该使用它或取消令牌?我的猜测是Timeout针对非异步/等待的情况?

c# cancellationtokensource dotnet-httpclient cancellation-token

6
推荐指数
1
解决办法
932
查看次数

在异步无效中取消任务

嗨,我有一个列表框 每当用户选择一个项目时,就会向网络发送一个请求 现在我想在用户选择该项目时取消之前的操作,然后开始新的操作。

我使用以下代码来做到这一点,我想知道这些代码是否工作正常。还是我应该尝试另一种方式?

private CancellationTokenSource ts = new CancellationTokenSource();
private async void Subf2mCore(CancellationToken ct)
{
  HtmlDocument doc = await web.LoadFromWebAsync(url);
   ...
  foreach (var node in doc)
  {
    if (!ct.IsCancellationRequested)
    {
      ....
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我以这种方式运行 func

ts?.Cancel();
ts = new CancellationTokenSource();
Subf2mCore(ts.Token);
Run Code Online (Sandbox Code Playgroud)

c# task cancellation cancellationtokensource

6
推荐指数
1
解决办法
313
查看次数

处理取消令牌源的正确模式

考虑这样一个场景,您需要完成一些异步工作,并且可以在即发即弃模式下运行它。这种异步工作能够侦听取消,因此您向它传递取消令牌以便能够取消它。

在给定的时刻,我们可以决定请求取消正在进行的活动,方法是使用我们从中获取取消令牌的取消令牌源对象。

因为取消令牌源实现了IDisposable,所以我们应该尽可能地调用它的Dispose方法。这个问题的重点是确定您何时完成给定的取消令牌源。

假设您决定通过调用Cancel取消令牌源上的方法来取消正在进行的工作:在调用之前是否需要等待正在进行的操作完成Dispose

换句话说,我应该这样做:

class Program 
{
  static void Main(string[] args) 
  {
    var cts = new CancellationTokenSource();
    var token = cts.Token;

    DoSomeAsyncWork(token); // starts the asynchronous work in a fire and forget manner

    // do some other stuff here 

    cts.Cancel();
    cts.Dispose(); // I call Dispose immediately after cancelling without waiting for the completion of ongoing work listening to the cancellation requests via the token

    // do some other …
Run Code Online (Sandbox Code Playgroud)

c# task-parallel-library async-await cancellationtokensource .net-core

6
推荐指数
2
解决办法
1289
查看次数

Azure函数HTTP触发器不取消请求

当我取消从浏览器到 HTTP 触发器的请求时,它不会取消,而是在 Azure 上托管时继续执行。

我的函数示例:

[FunctionName("Test")]
public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
    CancellationToken cancellationToken,
    ILogger log)
{
    var allCancellationTokens = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, req.HttpContext.RequestAborted);

    await Task.Delay(30000, allCancellationTokens.Token);

    if (allCancellationTokens.IsCancellationRequested) {
        log.LogInformation("Request was cancelled!");
        return new StatusCodeResult(499);
    }

    return new OkObjectResult("Complete");
}
Run Code Online (Sandbox Code Playgroud)

我一直在通过 Postman 和 axios 取消令牌测试取消。当我在本地运行项目并取消它时,它可以工作,但一旦发布到天蓝色,它似乎就不会取消。

我的预期结果是,OperationCanceledException如果我在执行期间取消请求,它会抛出await Task.Delay(30000, allCancellationTokens.Token);异常。但是,在检查 Azure Functions 上的日志时,似乎只是继续执行并完成该函数。

重现步骤:

  1. 创建一个像上面定义的那样的 HTTP 触发器。
  2. 将应用程序发布到 Azure。
  3. 在 Azure 上的监视器部分中打开函数日志。
  4. 使用Postman,向该函数发送请求并取消请求(在30秒的超时时间内)。
  5. 不会取消请求并且仍会执行。

c# azure cancellationtokensource cancellation-token azure-functions

5
推荐指数
1
解决办法
1425
查看次数