我正在使用以下代码开始一项任务:
var token = tokenSource.Token;
var taskWithToken = new Task(() =>
new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute(),
token);
在我的继续中,我需要知道batchRunId以及可能在...
中列出的其他一些变量,但是,它并不能说明这是可能的???
taskWithToken.ContinueWith(task =>
{
if (!task.IsCanceled)
return;
//TODO: make sure no more subsequent runs happen
//TODO: sync with source data
}
);
我有什么遗失的吗?如何通过访问所需的值来确保.ContinueWith
执行?
答案 0 :(得分:4)
首先,我甚至不确定你的案子是否需要延续。您的代码可以简化为:
var taskWithToken = new Task(() =>
{
new ProcessMyCommand(_unitOfWork, ..., batchRunId, token).Execute();
// code from the continuation here
},
token);
但是如果你确实想要使用ContinueWith()
并且由于ReSharper警告你担心使用它,那么你不必这样做。大多数情况下,这样的代码非常好,您可以忽略警告。
更长的版本:当你编写一个引用封闭范围(所谓的closure)的lambda时,编译器必须为此生成代码。这究竟是一个实现细节,但是当前编译器为单个方法中的所有闭包生成一个闭包类。
在您的情况下,这意味着编译器会生成一个包含本地this
(因为_unitOfWork
),request
和batchRunId
(以及其他人)的类你没有表现出来)。这个闭包对象在new Task
lambda和ContinueWith()
lambda之间共享,即使第二个lambda不使用request
或this
。只要从某个地方引用第二个lambda,就不能对这些对象进行垃圾回收,即使它们无法从中进行访问。
所以,这种情况可能会导致内存泄漏,我相信这就是ReSharper警告你的原因。但几乎在所有情况下,这种内存泄漏都不存在(因为第二个lambda的引用时间不比第一个lambda长)或者它非常小。因此,大多数情况下,您可以放心地忽略该警告。但如果你得到神秘的内存泄漏,你应该调查你使用lambdas的方式,特别是你得到这个警告的地方。
答案 1 :(得分:2)
您可以创建MyTaskData
类来存储数据和结果,也可以存储MyTaskData PreviousTaskData
属性(来自上一个任务),创建结果链表。在其中创建一个Task<MyTaskData>
,最后是return myNewTaskData;
。然后在ContinueWith<MyTaskData>(...)
内,您可以通过Task.Result
属性获取之前的结果。
至于已取消Task
ContinueWith
的延续,其中包含TaskContinuationOptions
参数(MSDN)的变体,您可以在其中指定NotOnCanceled