gpt4 book ai didi

c# - 是否可以将 `ref bool` 转换为 CancellationToken?

转载 作者:行者123 更新时间:2023-12-02 04:33:39 27 4
gpt4 key购买 nike

我有一个遗留场景,其中使用 ref bool 向实现发送取消信号。现在,我想调用一个基于 Task 的库方法,该方法采用 CancellationToken 实例,我也希望在 bool 值更改时取消该实例。

这就是我必须处理的事情:

void Method(ref bool isCancelled)
{
while (!isCancelled)
{
...
DoThis();
DoThat();
...
}
}

这就是我想做的:

Task MethodAsync(ref bool isCancelled)
{
while (!isCancelled)
{
...
DoThis();
await DoTheNewThingAsync(isCancelled.ToCancellationToken());
DoThat();
...
}
}

ToCancellationToken() 当然在此上下文中不存在,仅用于显示意图。

我尝试创建 CancellationTokenSource 的自定义实现,但该类中没有任何可以使用的虚拟内容。也不可能直接创建自定义 CancellationToken,因为它是一个 struct 并且无法继承。

我知道使用 ref bool 是一种糟糕的做法,但我目前无法更改依赖它的底层实现,因此我需要一种方法来使用它的值作为取消基于任务的调用机制。

最佳答案

这很复杂。出于以下几个原因:

  1. 您无法通过 ref 将参数传递给 async 方法。您正在使用 await,但要使用 await,您的方法需要标记为 async。并且async方法不能有ref参数。例如,这不会编译:
async Task MethodAsync(ref bool isCancelled)
{
while (!isCancelled)
{
DoThis();
await DoTheNewThingAsync(isCancelled.ToCancellationToken());
DoThat();
}
}

这会给你编译器错误:

CS1988: Async methods cannot have ref, in or out parameters

  • 您不能在匿名方法中使用 ref 参数。我考虑过使用 Timer 来检查变量。像这样的事情:
  • public static CancellationToken ToCancellationToken(ref bool isCancelled)
    {
    var tokenSource = new CancellationTokenSource();

    var timer = new System.Timers.Timer()
    {
    AutoReset = true,
    Interval = 100
    };
    timer.Elapsed += (source, e) =>
    {
    if (isCancelled)
    {
    tokenSource.Cancel();
    timer.Dispose();
    }
    };
    timer.Enabled = true;

    return tokenSource.Token;
    }

    但这会给你编译器错误:

    CS1628: Cannot use ref, out, or in parameter 'isCancelled' inside an anonymous method, lambda expression, query expression, or local function

    我没有看到任何其他方法可以通过引用将 bool 放入事件处理程序。

  • 我能得到的最接近的是这样的:
  • void Method(ref bool isCancelled)
    {
    while (!isCancelled)
    {
    DoThis();
    using (var tokenSource = new CancellationTokenSource()) {
    var mytask = DoTheNewThingAsync(tokenSource.Token);
    while (true)
    {
    //wait for either the task to finish, or 100ms
    if (Task.WaitAny(mytask, Task.Delay(100)) == 0)
    {
    break; //mytask finished
    }
    if (isCancelled) tokenSource.Cancel();
    }

    // This will throw an exception if an exception happened in
    // DoTheNewThingAsync. Otherwise we'd never know if it
    // completed successfully or not.
    mytask.GetAwaiter().GetResult();
    }
    DoThat();
    }
    }

    但是,这会阻止调用者,所以我不完全明白这有什么用(如果被阻止,调用者如何更改 isCancelled?)。但这就是您现有方法正在做的事情,所以也许它会起作用?

    但这太hacky了。如果您完全可以控制上游如何完成任何事情,那就这样做。

    关于c# - 是否可以将 `ref bool` 转换为 CancellationToken?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58661375/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com