I am starting a task with the following code:
var token = tokenSource.Token;
var taskWithToken = new Task(() =>
new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute(),
token);
In my continue with, I need to know the batchRunId and possibly some other variables listed in the ...
, however, it doesn't apepar that this is possible???
taskWithToken.ContinueWith(task =>
{
if (!task.IsCanceled)
return;
//TODO: make sure no more subsequent runs happen
//TODO: sync with source data
}
);
Is there something I am missing? How can I make sure the .ContinueWith
executes with access to the values it needs?
You can create your
MyTaskData
class to store your data and result and it may as well storeMyTaskData PreviousTaskData
property (from previous task) creating linked list of results. Create aTask<MyTaskData>
inside which, at the end, youreturn myNewTaskData;
. ThenContinueWith<MyTaskData>(...)
inside which you can get previous results throughTask.Result
property. As for continuation on cancelledTask
ContinueWith
has a variant withTaskContinuationOptions
parameter (MSDN) where you can specifyNotOnCanceled
First, I'm not even sure if you need continuation in your case. Your code could be simplified into something like:
But if you do want to use
ContinueWith()
and you're worried about using it because of the ReSharper warning, then you don't have to. Most of the time, code like this is perfectly fine and you can ignore the warning.Longer version: when you write a lambda that references something from the enclosing scope (so called closure), the compiler has to generate code for that. How exactly does it do that is an implementation detail, but the current compiler generates a single closure class for all closures inside a single method.
What this means in your case is that the compiler generates a class that contains the locals
this
(because of_unitOfWork
),request
andbatchRunId
(and maybe others that you didn't show). This closure object is shared between thenew Task
lambda and theContinueWith()
lambda, even though the second lambda doesn't userequest
orthis
. And as long as the second lambda is referenced from somewhere, those objects can't be garbage collected, even though they can't be accessed from it.So, this situation can lead to a memory leak, which I believe is why ReSharper is warning you about it. But in almost all cases, this memory leak either doesn't exist (because the second lambda isn't referenced longer than the first one) or it's very small. So, most of the time, you can safely ignore that warning. But if you get mysterious memory leaks, you should investigate the way you're using lambdas and especially places where you get this warning.