【问题标题】:Accessing the task returned by ContinueWith in the ContinueWith action good or bad? [duplicate]在 ContinueWith 操作中访问 ContinueWith 返回的任务是好是坏? [复制]
【发布时间】:2021-02-01 18:51:26
【问题描述】:

我想运行一个任务并在完成后将其从列表中删除。 更准确地说,我想删除 ContinueWith 任务,而不是任务本身,见下文:

void RunTask(Action someAction)
{
    var task = new Task(someAction);

    Task? continueWithTask = null;
    continueWithTask = task.ContinueWith(_ =>
    {
        _runningTasks.Remove(continueWithTask); // <- Is there a better/safer way to access the continueWithTask?
    });

    _runningTasks.Add(continueWithTask);
    task.Start();
}

我的问题实际上是关于在 ContinueWith 操作本身中访问 continueWithTask 的方式,因为这里编译器警告 continueWithTask 可能为空(甚至如果它不在运行时)。

【问题讨论】:

  • 请注意,显示的代码不会产生正确结果,因此请确保修复您编写的代码确实证明了问题,因此它无法从_runningTasks中删除任务在将其添加到列表之前列出。
  • 正如@AlexeiLevenkov 所暗示的,应该在开始任务之前将continueWithTask 添加到_runningTasks
  • 有关警告的处理,请参阅“null forgiving”运算符,一式两份。使用它是“好”还是“坏”是一个见仁见智的问题,因此不适合 Stack Overflow 作为一个问题。有关如何修复当前损坏的代码,请参阅上面的 cmets。
  • 您是否有任何理由要专门提及continuationTask 而不是task
  • 是的,安德鲁,原因是我需要考虑任务一旦从列表中删除,而不是之前,你明白我的意思吗?

标签: c# task


【解决方案1】:

我认为您实现延续的方式没有任何问题错误,但还有另一种选择:

void RunTask(Action someAction)
{
    var task = new Task(someAction);
    _runningTasks.Add(task);
    var _ = task.ContinueWith(t => _runningTasks.Remove(t));
    task.Start(); // Note that this should happen AFTER _runnningTasks.Add, as per the comments
}

将完成的任务作为参数赋予延续函数,因此您不必捕获对它的引用。你可以保证传入函数的参数永远不会为空。

【讨论】:

  • “延续函数以完成的任务为参数” -- 请重新阅读原题。 OP确实希望task作为要删除的对象,因此使用传递给延续委托的对象是完全错误的。
  • 我没有看到 - 我会要求 OP 澄清他们为什么有这个限制
猜你喜欢
  • 1970-01-01
  • 2014-07-15
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多