1

タスク並列ライブラリの ContinueWith が何をしているように見えるのか、少し混乱しています。

私の理解では、タスクが完了するまでこれを呼び出すべきではありません。while true ループにいる場合、これはまったく呼び出されるべきではありません。

        DateTime t = DateTime.Now.AddSeconds(10);
        Task.Factory.StartNew(async () =>
            {
                while (true)
                {
                    if (t < DateTime.Now)  //after 10s throw
                    { 
                        throw new Exception(); //I expect it to run the continuation here
                    }

                    Console.WriteLine("looped");
                    await Task.Delay(new TimeSpan(0, 0, 1));
                }
            }
        ).ContinueWith(ct => Console.WriteLine("Continued with: {0}",ct.Result.Status)) ;

次のコードは、例外がスローされるまで ContinueWith メソッドを実行しないと予想されますが、そうではありません。代わりに、次の出力が得られます。

looped
Continued with: WaitingForActivation
looped
looped
looped
looped
looped
looped
looped
looped
looped

最初の遅延に達したときに、ContinueWith が呼び出されるのはなぜですか?

4

3 に答える 3

6

ラムダが a を返し、そのラムダがスレッドプールで実行されるため、返されるタスクTask.Factory.StartNewは aです。そのラムダの結果は a でラップされ、そのプロパティに入れられます。Task<Task>TaskTask<T>Result

したがって、 を呼び出すUnwrapか、より適切に使用する必要がありますTask.Run

于 2013-08-15T20:34:02.060 に答える
4

あなたは邪悪なasync void代理人を作成しました。

Task同期部分が完了するとすぐに終了します (オリジナルを完成させます)。
元のデリゲートの非同期部分を観察する方法はありません。

元のデリゲートはTask、操作の非同期部分を表す非同期を返します。
ただし、Task同期部分が終了するとすぐに外側が完了し、内側が完了するのを待つことはありませんTask

代わりに、Task.Run()を受け入れる を呼び出す必要がありますFunc<Task>
このようにして、元のデリゲートの非同期部分が元のタスクに貢献します。

于 2013-08-15T20:33:54.220 に答える
0

ContinueWithTask前の呼び出しから a が返された瞬間に呼び出す必要があります。はTask、終了する前に前回の呼び出しから返されます。

編集: 実際、SLaks は本当の問題を特定しました。この場合、あまり関連性はありませんが、私の声明は依然として真実です。:)

于 2013-08-15T20:34:13.310 に答える