0

製品ごとにさまざまなファイルを収集する方法があります。他のWebサイトからファイルをダウンロードするため、そのメソッドを非同期にしたいと考えています。このコードを作成しました:

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 にアクセスしようとすると、それらは単なる空のオブジェクトです。私の「ゲッター」メソッドは問題なく返されることがわかりますが、データは product.SDS プロパティなどには到達しません。

4

2 に答える 2

1

ContinueWith既存のタスクを変更するのではなく、継続が完了すると完了する新しいタスクを返します。apbTask呼び出しの結果を待っているはずの元のタスク ( など) を待っていContinueWithます。

于 2013-07-23T13:46:59.497 に答える
1

コードは、変更された製品への参照を更新しようとしています。継続が実行されるとき、指されるインスタンスは、その時点でproduct外部変数が持っている値です。productリストの最後の製品、またはその他の製品である可能性があります。

これはバグではありませんが、外部変数のキャプチャがラムダで機能する方法です。

外部変数にアクセスしようとする代わりに、その値をTaskFactory.StartNew(Action(Of Object),Object)に状態値として渡します。

同じことが ContinueWith の呼び出しにも当てはまります。前のステップで使用された製品を変更したい場合は、おそらくタプルを使用して、結果の一部として次のステップに渡す必要があります。

于 2013-07-24T08:47:09.537 に答える