1

我对任务并行库中的 ContinueWith 似乎做了什么感到有点困惑。

我的理解是,在任务完成之前不应该调用它。如果我处于一个真正的循环中,则根本不应该调用它。

        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

从返回的任务Task.Factory.StartNew是 aTask<Task>因为您的 lambda 返回 aTask并且该 lambda 在线程池上运行。该 lambda 的结果被包装在 a 中Task<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

ContinueWith应该Task在从前一个调用返回 a 的那一刻调用。在Task完成之前从上一个调用返回。

编辑:实际上,SLaks 已经确定了真正的问题。我的陈述仍然正确,尽管在这种情况下不太相关。:)

于 2013-08-15T20:34:13.310 回答