等待任务返回WaitingForActivation?

3

我有一个消费者/生产者设置,共享一个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循环? 它不应该一直阻塞直到cancellationToken被取消吗?

内部的GetFooAsync是否导致某些行为从Foreach中断?

1个回答

6
您当前的代码会在第一个await处调用HandleConsumerStopped,因为这是异步方法返回给调用者的时候。请注意,您的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的中间运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接