await Task返回WaitingForActivation?

时间:2014-11-19 15:36:26

标签: c# task-parallel-library async-await

我有一个消费者/生产者设置共享一个BlockingCollection。

public void StartConsumer(CancellationToken cancellationToken)
{
    Task.Factory.StartNew(async () =>
     {               

         foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
         {
             var rowsAffected = await  GetFooAsync(value.Id);                     
         }                

     }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current)
     .ContinueWith(task => HandleConsumerStopped(task, cancellationToken), cancellationToken);
}

从第一个帖子返回到' ContinueWith'始终是任务的结果。 并且该任务的结果是“WaitingForActivation'

所以,我的问题是,为什么它出现在foreach循环中? 是否应该在取消予取消之前阻止?

是iner GetFooAsync导致某些行为从Foreach中断?

1 个答案:

答案 0 :(得分:6)

您的当前代码会在遇到第一个HandleConsumerStopped时立即调用await,因为那时您的异步方法会返回给调用者。请注意,您的StartNew返回Task<Task>,您需要为内部任务附加延续。目前,您的代码将其附加到外部任务中。

如果要完成整个异步方法的完成,只需在异步方法本身内调用HandleConsumerStopped方法即可。

Task.Factory.StartNew(async () =>
 { 
     foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
     {
         var rowsAffected = await  GetFooAsync(value.Id);                     
     }

     HandleConsumerStopped();//Parameters removed
 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);

如果您不得不使用ContinueWith,则需要使用Task.Run,或者需要致电Unwrap。如果您使用Task.Run,则会获得UnWrap免费但没有TaskCreationOptions个标记。

 Task.Factory.StartNew(async () =>
 {          
     foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
     {
         var rowsAffected = await GetFooAsync(value.Id);                     
     }                

 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current)
 .UnWrap()//Note the unwrap here
 .ContinueWith(task => HandleConsumerStopped(task, cancellationToken), cancellationToken);

现在HandleConsumerStopped将在StartNew的整个主体完成后运行,而不是在foreach的中间。