-2

I want to run a Task and remove it from a list once it is completed. More precisely, I want to remove the ContinueWith task, not the task itself, see below:

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();
}

My question here is really about the way of accessing the continueWithTask in the ContinueWith action itself, because here the compiler warns on the fact that continueWithTask might be null (even if it isn't at runtime).

Kino101
  • 765
  • 8
  • 18
  • 1
    Please note that code shown will not produce *correct* results, so make sure to fix that code you wrote do demonstrate the problem so it can't remove task from `_runningTasks` list before it is added to the list. – Alexei Levenkov Feb 01 '21 at 19:00
  • 1
    As @AlexeiLevenkov alluded to, should probably add `continueWithTask` to `_runningTasks` *before* starting the task. – Chris Yungmann Feb 01 '21 at 19:02
  • For dealing with the warning, see "null forgiving" operator, in duplicate. Whether the use of this is "good" or "bad" is a matter of opinion and so unsuitable for Stack Overflow as a question. See comments above for how to fix your currently-broken code. – Peter Duniho Feb 01 '21 at 19:32
  • Is there any reason you want to refer specifically to `continuationTask` and not `task`? – Andrew Williamson Feb 01 '21 at 20:12
  • Yes Andrew, the reason is that I need to consider the task finished once is it removed from the list, not before, do you see what I mean? – Kino101 Feb 01 '21 at 21:35
  • Alexei Levenkov yes, your remark is correct, but that wasn't the point and even if I add to the list before, what if the Start throws ? – Kino101 Feb 01 '21 at 21:42
  • I changed the code to avoid confusion. – Kino101 Feb 01 '21 at 21:46
  • In this example, you are never referring to the task from anywhere else, so it shouldn't matter if the task is removed after it has completed but before the continuation has completed. Do you ever refer to the `continueWith` task from outside of this method? – Andrew Williamson Feb 01 '21 at 23:36

1 Answers1

-1

I don't think there's anything wrong with the way you have implemented the continuation, but there is an alternative:

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
}

The continuation function is given the completed task as a parameter, so you don't have to capture a reference to it. You can guarantee that the argument passed in to the function will never be null.

Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
  • _"The continuation function is given the completed task as a parameter"_ -- please re-read the original question. The OP does _not_ want `task` as the object to remove, so using the object passed to the continuation delegate is completely wrong. – Peter Duniho Feb 01 '21 at 19:33
  • I didn't see that - I will ask the OP for clarification on why they have this constraint – Andrew Williamson Feb 01 '21 at 20:12