c# - 正确使用 CancellationToken

标签 c# cancellationtokensource cancellation-token

这是我的情况:

    private CancellationTokenSource cancellationTokenSource;
    private CancellationToken cancellationToken;

    public IoTHub()
    {
        cancellationTokenSource = new CancellationTokenSource();
        cancellationToken = cancellationTokenSource.Token;

        receive();
    }

    private void receive()
    {
        eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint);
        var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds;

        foreach (string partition in d2cPartitions)
        {
            ReceiveMessagesFromDeviceAsync(partition, cancellationToken);
        }
    }

    private async Task ReceiveMessagesFromDeviceAsync(CancellationToken ct)
    {
        var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow);

        while (true)
        {
            if(ct.IsCancellationRequested)
            {
                break;
            }

            EventData eventData = await eventHubReceiver.ReceiveAsync();
            if (eventData == null) continue;

            string data = Encoding.UTF8.GetString(eventData.GetBytes());

            // Javascript function with Websocket
            Clients.All.setMessage(data);
        }
    }

    public void cancelToken()
    {
      cancellationTokenSource.Cancel();
    }

当调用 cancelToken 方法时,任务不会被取消。怎么会?

我已阅读Microsoft guide ,关于任务取消的其他 Stackoverflow 问题。

但仍然难以正确使用它们。

最佳答案

您可以将 CancellationToken 视为一个标志,指示是否收到取消信号。因此:

while (true)
{
    //you check the "flag" here, to see if the operation is cancelled, correct usage
    if(ct.IsCancellationRequested)
    {
        break;
    }

    //your instance of CancellationToken (ct) can't stop this task from running
    await LongRunningTask();
}

如果你想取消LongRunningTask,你应该在任务体内使用CancellationToken,并在必要时检查它,像这样:

async Task LongRunningTask()
{
    await DoPrepareWorkAsync();

    if (ct.IsCancellationRequested)
    {
        //it's cancelled!
        return;
    }

    //let's do it
    await DoItAsync();

    if (ct.IsCancellationRequested)
    {
        //oh, it's cancelled after we already did something!
        //fortunately we have rollback function
        await RollbackAsync();
    }
}

关于c# - 正确使用 CancellationToken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36173674/

相关文章:

F# Async.RunSynchronously 带有超时和取消 token

c# - 我是否应该始终将 CancellationToken 添加到我的 Controller 操作中?

c# - C# 有没有办法将 "type"变为 long ?

c# - 如何捕获 CancellationToken.Register 回调异常?

c# - 为什么 CancellationToken 与 CancellationTokenSource 是分开的?

c# - 一种类似于 CancellationTokenSource 和 CancellationToken 模式的暂停线程模式?

c# - 在 Startup 的 Configure 方法中注入(inject) cancellation-token

c# - 创建 System.Drawing.Point 类型的运行时对象时出错

c# - FluentValidation 调用规则集和通用规则

c# - 如何使用默认 Entity Framework 和默认日期值