我有一种方法可以为每个产品收集各种文件。我想让该方法异步,因为它从其他网站下载文件。我做了这个代码:
For Each product In productList
If model.Sds Then
Dim sdsTask As Task(Of ZipFile) = Task(Of ZipFile).Factory.StartNew(Function() GetSafetyDataSheets(product.Product))
sdsTask.ContinueWith(Sub(t)
product.SDS = t.Result
Debug.WriteLine("test")
End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
taskList.Add(sdsTask)
End If
If model.Apb Then
Dim apbTask As Task(Of List(Of ZipFile)) = Task(Of List(Of ZipFile)).Factory.StartNew(Function() GetAPB(product.Product, model.Department))
apbTask.ContinueWith(Sub(t) product.Instruction = t.Result)
taskList.Add(apbTask)
End If
If model.Pdb Then
Dim pdbTask As Task(Of ZipFile) = Task(Of ZipFile).Factory.StartNew(Function() GetProductDatasheet(product.Product))
pdbTask.ContinueWith(Sub(t) product.PDB = t.Result)
taskList.Add(pdbTask)
End If
Next
Task.WaitAll(taskList.ToArray)
但是当它等待并且我试图访问我的产品列表中的产品中的SDS,APB或PDB时,它们只是空对象。我可以看到我的“getter”方法返回正常,但数据从未进入product.SDS属性等。
答案 0 :(得分:1)
ContinueWith
不会修改现有任务,而是返回一个新任务,该任务将在延续完成后完成。您正在等待原始任务(例如apbTask
),您应该在等待ContinueWith
来电的结果。
答案 1 :(得分:1)
您的代码尝试更新对已更改的产品的引用。当延续运行时,product
指向的实例是外部product
变量当时具有的值。它可能是列表中的最后一个产品,也可能是任何其他产品。
这不是一个bug,而是外部变量捕获与lambdas一起使用的方式。
不是尝试访问外部变量,而是将其值作为状态值传递给TaskFactory.StartNew(Action(Of Object),Object)。
对ContinueWith的调用也是如此。如果要修改上一步中使用的产品,则应将其作为结果的一部分传递给下一步,也许使用Tuple来执行此操作。