标签: cancellation-token

任务构造函数中的取消令牌:为什么?

某些System.Threading.Tasks.Task构造函数将a CancellationToken作为参数:

CancellationTokenSource source = new CancellationTokenSource();
Task t = new Task (/* method */, source.Token);
Run Code Online (Sandbox Code Playgroud)

令我感到困惑的是,从方法体内部无法实际获取传入的令牌(例如,没有什么比这样Task.CurrentTask.CancellationToken).必须通过某种其他机制提供令牌,例如状态对象或在lambda中捕获.

那么在构造函数中提供取消令牌的目的是什么呢?

c# .net-4.0 task-parallel-library cancellation-token

214
推荐指数
4
解决办法
5万
查看次数

为什么CancellationToken与CancellationTokenSource是分开的?

我正在寻找除了CancellationTokenSource类之外还引入.NET CancellationToken结构的原因.我的理解是如何的API被使用,但想也明白为什么它就是这样设计的.

即,我们为什么要:

var cts = new CancellationTokenSource();
SomeCancellableOperation(cts.Token);

...
public void SomeCancellableOperation(CancellationToken token) {
    ...
    token.ThrowIfCancellationRequested();
    ...
}
Run Code Online (Sandbox Code Playgroud)

而不是直接传递CancellationTokenSource,如:

var cts = new CancellationTokenSource();
SomeCancellableOperation(cts);

...
public void SomeCancellableOperation(CancellationTokenSource cts) {
    ...
    cts.ThrowIfCancellationRequested();
    ...
}
Run Code Online (Sandbox Code Playgroud)

这是一个基于以下事实的性能优化:取消状态检查比传递令牌更频繁吗?

因此CancellationTokenSource可以跟踪和更新CancellationTokens,并且对于每个令牌,取消检查是本地字段访问?

鉴于两种情况下没有锁定的挥发性bool就足够了,我仍然无法理解为什么会更快.

谢谢!

.net multithreading task-parallel-library cancellationtokensource cancellation-token

119
推荐指数
4
解决办法
2万
查看次数

CancellationToken的默认参数

我有一些异步代码,我想添加一个CancellationToken.但是,有许多实现不需要这样做,所以我想有一个默认参数 - 也许是CancellationToken.None.然而,

Task<x> DoStuff(...., CancellationToken ct = null)
Run Code Online (Sandbox Code Playgroud)

产量

类型''的值不能用作默认参数,因为没有标准转换来键入'System.Threading.CancellationToken'

Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)
Run Code Online (Sandbox Code Playgroud)

'ct'的默认参数值必须是编译时常量

有没有办法让CancellationToken有一个默认值?

c# asynchronous task-parallel-library cancellation-token

76
推荐指数
5
解决办法
2万
查看次数

如何在不变丑的情况下使方法可以取消?

我目前正在改进我们长期运行的方法,以便取消.我打算使用System.Threading.Tasks.CancellationToken来实现它.

我们的方法通常执行一些长时间运行的步骤(主要向硬件发送命令然后等待硬件),例如

void Run()
{
    Step1();
    Step2();    
    Step3();
}
Run Code Online (Sandbox Code Playgroud)

我对取消的第一个(也许是愚蠢的)想法会将其转化为

bool Run(CancellationToken cancellationToken)
{
    Step1(cancellationToken);

    if (cancellationToken.IsCancellationRequested)
        return false;

    Step2(cancellationToken);

    if (cancellationToken.IsCancellationRequested)
        return false;    

    Step3(cancellationToken);

    if (cancellationToken.IsCancellationRequested)
        return false;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

坦率地看起来很可怕.这种"模式"也将在单个步骤内继续(并且它们必然已经相当长).这会使Thread.Abort()看起来很性感,虽然我知道它不推荐.

有没有更清晰的模式来实现这一点,不会隐藏许多样板代码下面的应用程序逻辑?

编辑

作为步骤性质的一个例子,该Run方法可以阅读

void Run()
{
    GiantRobotor.MoveToBase();
    Oven.ThrowBaguetteTowardsBase();    
    GiantRobotor.CatchBaguette();
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我们正在控制需要同步的不同硬件单元才能协同工作.

c# multithreading cancellation-token

47
推荐指数
4
解决办法
3254
查看次数

如何正确重置CancellationToken?

async ctp今天早上我一直在玩,并有一个简单的程序与a button和a label.点击button它开始更新label,停止button它停止写入label.但是,我不确定如何重置,CancellationTokenSource以便我可以重新启动该过程.我的代码如下:

public partial class MainWindow : Window
{
    CancellationTokenSource cts = new CancellationTokenSource();
    public MainWindow()
    {
        InitializeComponent();
        button.Content = "Start";
    }

    async Task DoWork(CancellationToken cancelToken)
    {
        int i = 0;
        while (!cancelToken.IsCancellationRequested)
        {
            label.Content = i++.ToString();
            await TaskEx.Delay(50, cancelToken);
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (button.Content == "Start")
        {
            button.Content = "Stop";
            DoWork(cts.Token);
        }
        else
        {
            button.Content = "Start";
            cts.Cancel(); …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous async-await cancellationtokensource cancellation-token

41
推荐指数
3
解决办法
2万
查看次数

我们应该将CancellationToken用于MVC/Web API控制器吗?

异步控制器有不同的示例.其中一些在方法定义中使用CancellationToken:

public async Task<ActionResult> ShowItem(int id, CancellationToken cancellationToken)
{
    await Database.GetItem(id, cancellationToken);
    ...
Run Code Online (Sandbox Code Playgroud)

但是其他示例甚至是VS2013的默认ASP.NET项目根本不使用CancellationToken而没有使用它:

public async Task<ActionResult> ShowItem(int id)
{
    await Database.GetItem(id);
    ...
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚,我们是否应该在控制器中使用CancellationToken(以及为什么).

c# asp.net-mvc async-await asp.net-web-api cancellation-token

41
推荐指数
3
解决办法
2万
查看次数

在Task.Run中使用CancellationToken超时不起作用

好的,我的问题非常简单.为什么这段代码不会抛出TaskCancelledException

static void Main()
{
    var v = Task.Run(() =>
    {
        Thread.Sleep(1000);
        return 10;
    }, new CancellationTokenSource(500).Token).Result;

    Console.WriteLine(v); // this outputs 10 - instead of throwing error.
    Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

但这一个有效

static void Main()
{
    var v = Task.Run(() =>
    {
        Thread.Sleep(1000);
        return 10;
    }, new CancellationToken(true).Token).Result;

    Console.WriteLine(v); // this one throws
    Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

.net c# task-parallel-library cancellationtokensource cancellation-token

32
推荐指数
4
解决办法
4万
查看次数

链接取消令牌

我使用传递的取消令牌,以便可以干净地关闭我的服务.该服务具有不断尝试连接到其他服务的逻辑,因此令牌是打破在单独线程中运行的这些重试循环的好方法.我的问题是我需要调用一个具有内部重试逻辑的服务,但是如果重试失败则在一段时间后返回.我想创建一个带有超时的新取消令牌,这将为我做到这一点.这个问题是我的新令牌没有链接到"主"令牌,所以当主令牌被取消时,我的新令牌仍然有效,直到它超时或建立连接并返回.我想要做的是将两个令牌链接在一起,这样当主要的一个被取消时,我的新一个也会取消.我尝试使用该CancellationTokenSource.CreateLinkedTokenSource方法但是当我的新令牌超时时,它也取消了主令牌.有没有办法做我需要做的令牌,或者它需要更改重试逻辑(可能不会轻易做到这一点)

这是我想要做的:

主令牌 - 传递各种功能,以便服务可以干净地关闭.临时令牌 - 传递给单个函数并在一分钟后设置为超时

如果取消主令牌,则还必须取消临时令牌.

当临时令牌到期时,它不得取消主令牌.

.net c# cancellationtokensource cancellation-token

32
推荐指数
4
解决办法
8598
查看次数

具有取消令牌的NetworkStream.ReadAsync永远不会取消

这里的证明.
知道这段代码有什么问题吗?

    [TestMethod]
    public void TestTest()
    {
        var tcp = new TcpClient() { ReceiveTimeout = 5000, SendTimeout = 20000 };
        tcp.Connect(IPAddress.Parse("176.31.100.115"), 25);
        bool ok = Read(tcp.GetStream()).Wait(30000);
        Assert.IsTrue(ok);
    }

    async Task Read(NetworkStream stream)
    {
        using (var cancellationTokenSource = new CancellationTokenSource(5000))
        {
            int receivedCount;
            try
            {
                var buffer = new byte[1000];
                receivedCount = await stream.ReadAsync(buffer, 0, 1000, cancellationTokenSource.Token);
            }
            catch (TimeoutException e)
            {
                receivedCount = -1;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

.net sockets async-await .net-4.5 cancellation-token

30
推荐指数
4
解决办法
2万
查看次数

默认(CancellationToken)是否等同于CancellationToken.None?

看看CancellationToken.None它的实现,它只是回归default(CancellationToken).但是,我在CancellationToken文档中看不到两者是等价的.

我想提供这样的API,但直到我确定它总能工作:

Task DoSomething(CancellationToken token = default(CancellationToken))
Run Code Online (Sandbox Code Playgroud)

它定义的行为default(CancellationToken)是否相同CancellationToken.None,或者这只是一个实现细节?

.net linq ado.net cancellation-token

28
推荐指数
3
解决办法
8523
查看次数